netizen-cli 0.14.0__tar.gz → 0.14.1__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.1}/PKG-INFO +1 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/__init__.py +1 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/static/admin.css +3 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/static/admin.js +36 -19
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/static/index.html +32 -0
- netizen_cli-0.14.1/netizen_cli/admin/static/progress-card.js +118 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/web.py +52 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/bindings.py +11 -7
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/controls.py +15 -10
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel_app.py +1 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/codex_runtime.py +19 -7
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/database_migrations.py +2 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/main.py +6 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/management/service.py +25 -0
- netizen_cli-0.14.1/netizen_cli/migrations/v19.py +94 -0
- netizen_cli-0.14.1/netizen_cli/progress_card_config.py +45 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/session_settings.py +10 -6
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/sessions/policy.py +12 -14
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/settings.py +8 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/worktrees/service.py +1 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/worktrees/settings.py +16 -16
- {netizen_cli-0.14.0 → netizen_cli-0.14.1/netizen_cli.egg-info}/PKG-INFO +1 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli.egg-info/SOURCES.txt +6 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/pyproject.toml +1 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/admin.md +19 -3
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/feedback-and-files.md +11 -4
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/sessions.md +5 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_binding_scheduled_channel.py +6 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cards.py +2 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_channel_app.py +6 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cli_data.py +6 -6
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_codex_runtime.py +170 -3
- netizen_cli-0.14.1/tests/test_configuration_publication.py +132 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_database_migrations.py +4 -4
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_defaults_cards.py +5 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_migration_schema_validation.py +1 -1
- netizen_cli-0.14.1/tests/test_optional_progress_card_settings_migration.py +140 -0
- netizen_cli-0.14.1/tests/test_progress_card_config.py +107 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_progress_card_entrypoints.py +33 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_progress_card_settings_migration.py +5 -5
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedule_workspace_migration.py +2 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_scheduled_runtime.py +12 -3
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_session_defaults_migration.py +3 -3
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_session_external_runtime.py +13 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_session_settings.py +8 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_worktree_service.py +25 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_worktree_tools_integration.py +6 -4
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/MANIFEST.in +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/README.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/_build.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/config.example.yaml +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/__main__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/account_rate_limits.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/auth.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/credentials.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/errors.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/feishu.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/login.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/port_config.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/presentation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/queries.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/static/chat-picker.css +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/static/chat-picker.js +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/static/identity.js +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/static/login.html +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/static/login.js +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/static/session-access.js +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/static/worktrees.js +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/transport.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/admin/users.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/builtin_skills.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/callbacks.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/chat_target.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/defaults.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/fork.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/model_info.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/pagination.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/questions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/reply.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/scheduled.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/session_ids.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/status.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/usage.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cards/workspace.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel/completion_mentions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel/input_preparation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel/messages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel/ports.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel/question_inputs.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel/reactions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel/reply_presenter.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel/session_pages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/channel/topics.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/chat_avatars.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/chat_targets.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cli.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cli_data.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cli_packages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cli_services.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cli_setup.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cli_update.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cli_update_restore.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/cli_update_worker.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/completion_mention.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/defaults/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/defaults/models.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/defaults/service.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/defaults/store.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/deployment/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/deployment/restart_worker.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/deployment/update_executor.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/deployment/update_protocol.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/domain.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/error_messages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/experience.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/feishu_app_onboarding.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/feishu_app_permissions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/feishu_links.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/git_status.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/image_inputs.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/instance.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/lark_app.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/management/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/management/blocking_io.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/management/chat_directory.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/management/chat_labels.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/management/coordination.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/management/updates.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/markdown_images.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/mcp_transport.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/message_content.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/message_history.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/message_preparation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/message_projection.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/migrations/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/migrations/schema.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/migrations/v14.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/migrations/v15.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/migrations/v16.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/migrations/v17.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/migrations/v18.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/model_settings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/package_resources.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/pagination.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/partial_answers.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/progress_card_settings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/projects.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/prompt_projection.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/quoted_context.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/result_images.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/runtime/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/runtime/contracts.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/runtime/name_writes.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/runtime/thread_naming.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/schedules/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/schedules/mcp.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/schedules/models.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/schedules/scheduler.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/schedules/service.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/schedules/store.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/sdk_gap_adapter.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/service_launcher.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/session_inventory.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/sessions/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/sessions/delegation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/sessions/errors.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/sessions/mcp.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/sessions/presentation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/sessions/schema.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/sessions/service.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/skill_references.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/task_text.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/terminal_cleanup.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/thread_history.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/turn_activity.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/turn_files.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/turn_patch_children.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/turn_plan_observer.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/user_questions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/worktrees/errors.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/worktrees/git.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/worktrees/models.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/worktrees/policy.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli/worktrees/store.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli.egg-info/dependency_links.txt +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli.egg-info/entry_points.txt +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli.egg-info/requires.txt +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/netizen_cli.egg-info/top_level.txt +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/setup.cfg +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-lark/SKILL.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/SKILL.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/commands.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/concepts.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/faq.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/fork-side-goal.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/messages.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/native-capabilities.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/scheduled-tasks.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/session-collaboration.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/status-and-control.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/skills/netizen-user-guide/references/user-guide.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_account_rate_limits.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_admin_update_executor_probe.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_bindings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_channel_fixtures.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_channel_input_preparation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_chat_avatars.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_chat_target_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_check_sdk.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cli.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cli_distribution.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cli_integration.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cli_packages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cli_packaging.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cli_services.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cli_setup.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cli_update.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_codex_sdk_capabilities.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_codex_sdk_upgrade_0161.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_codex_sdk_upgrade_0163.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_completion_mention_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_completion_mentions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_completion_topic_delivery.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_cron_chat_targets.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_defaults_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_defaults_runtime.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_defaults_worktree_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_deployment.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_documentation_links.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_domain_experience.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_error_messages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_feishu_app_onboarding.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_feishu_app_permissions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_file_pagination.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_fork_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_git_status.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_goal_reply_separation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_image_inputs.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_lark_app.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_lark_sdk_contract.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_main.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_markdown_images.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_message_content.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_message_history.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_message_material_inputs.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_message_preparation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_model_info_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_model_settings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_name_writes.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_pagination.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_partial_answer_delivery.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_partial_answers.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_persistent_fork_bindings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_persistent_fork_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_persistent_fork_runtime.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_child_files.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_feishu_completion_mention.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_feishu_partial_answers.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_feishu_turn_file_card.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_persistent_fork.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_python_sdk.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_scheduled_tasks.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_sdk_completion_race.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_sdk_response_recovery.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_skill_execution.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_probe_thread_naming.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_progress_card_presentation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_project_delete_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_project_delete_runtime.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_project_deletion_storage.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_prompt_projection.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_question_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_question_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_question_target_parity.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_quoted_context.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_release_script.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_repository_hygiene.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_result_images.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_resume_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_retired_deployment.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_runtime_resume_activation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_runtime_thread_naming.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedule_card_retry.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedule_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedule_mcp.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedule_run_now.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedule_scope_matrix.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedule_service.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedule_workspace_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedule_workspace_service.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedule_workspace_storage.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_scheduled_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_scheduled_worktrees.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_scheduler.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_scheduler_presenter.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_schedules_storage.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_sdk_gap_adapter.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_service_launcher.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_session_card_pages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_session_collaboration_app.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_session_defaults.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_session_id_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_session_policy.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_session_tools.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_settings_projects.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_status_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_status_commands.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_task_text.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_terminal_cleanup.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_thread_history.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_thread_naming.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_turn_activity.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_turn_files.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_turn_patch_children.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_turn_patch_statistics.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_turn_plan_observer.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_update_executor.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_usage_card.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_usage_control.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_user_guide_skill.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_user_questions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_worktree_channel_cwd.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_worktree_git.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_worktree_new.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_worktree_runtime_cwd.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/tests/test_worktree_settings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.1}/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
|
}
|
|
@@ -3550,22 +3563,19 @@ function resetScheduleEndOffset() {
|
|
|
3550
3563
|
|
|
3551
3564
|
function defaultScheduleSessionSettings() {
|
|
3552
3565
|
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
|
-
} };
|
|
3566
|
+
message_context_mode: "current-only", progress_card_settings: null };
|
|
3558
3567
|
}
|
|
3559
3568
|
|
|
3560
3569
|
const progressCardFields = ["show-commentary", "show-operations", "show-plan", "commentary-limit",
|
|
3561
3570
|
"operation-limit", "commentary-max-chars", "operation-max-chars", "organization"];
|
|
3562
3571
|
|
|
3563
3572
|
function progressCardSettings(settings) {
|
|
3564
|
-
return settings.progress_card_settings ||
|
|
3573
|
+
return settings.progress_card_settings || window.NetizenProgressCard?.current();
|
|
3565
3574
|
}
|
|
3566
3575
|
|
|
3567
3576
|
function progressCardSettingsError(settings) {
|
|
3568
3577
|
const progress = progressCardSettings(settings);
|
|
3578
|
+
if (!progress) return "";
|
|
3569
3579
|
for (const [key, label, maximum] of [
|
|
3570
3580
|
["commentary_limit", "进展条数", 8], ["operation_limit", "操作条数", 16],
|
|
3571
3581
|
["commentary_max_chars", "进展摘要长度", 320], ["operation_max_chars", "操作摘要长度", 240],
|
|
@@ -3582,19 +3592,21 @@ function renderProgressCardSettings(input, settings) {
|
|
|
3582
3592
|
if (!container) return;
|
|
3583
3593
|
const progress = progressCardSettings(settings);
|
|
3584
3594
|
container.hidden = !settings.progress_card_enabled;
|
|
3595
|
+
const source = input("progress-source");
|
|
3596
|
+
if (source) source.hidden = settings.progress_card_settings !== null;
|
|
3585
3597
|
for (const node of container.querySelectorAll("input, select")) {
|
|
3586
3598
|
const field = node.id.split("-progress-").at(-1);
|
|
3587
3599
|
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
|
|
3600
|
+
if (field.startsWith("show-")) node.checked = progress?.[key] || false;
|
|
3601
|
+
else node.value = progress?.[key] ?? "";
|
|
3602
|
+
node.disabled = !progress || !settings.progress_card_enabled
|
|
3591
3603
|
|| (field.startsWith("commentary-") && !progress.show_commentary)
|
|
3592
3604
|
|| (field.startsWith("operation-") && !progress.show_operations);
|
|
3593
3605
|
}
|
|
3594
|
-
for (const [kind, shown] of [["commentary", progress
|
|
3606
|
+
for (const [kind, shown] of [["commentary", progress?.show_commentary], ["operation", progress?.show_operations]]) {
|
|
3595
3607
|
input(`progress-${kind}-capacity`).hidden = !shown;
|
|
3596
3608
|
}
|
|
3597
|
-
const error = progressCardSettingsError(settings);
|
|
3609
|
+
const error = progress ? progressCardSettingsError(settings) : "读取全局配置后可编辑过程卡细项。";
|
|
3598
3610
|
const note = input("progress-error");
|
|
3599
3611
|
note.textContent = error;
|
|
3600
3612
|
note.hidden = !error;
|
|
@@ -3662,11 +3674,13 @@ function changeSessionSettingsField(input, settings, models, field, baseTurn = n
|
|
|
3662
3674
|
else if (field === "progress") settings.progress_card_enabled = input("progress").checked;
|
|
3663
3675
|
else if (field === "completion-mention") settings.completion_mention_enabled = input("completion-mention").checked;
|
|
3664
3676
|
else if (field.startsWith("progress-") && progressCardFields.includes(field.slice(9))) {
|
|
3677
|
+
const progress = progressCardSettings(settings);
|
|
3678
|
+
if (!progress) return;
|
|
3665
3679
|
const key = field.slice(9).replaceAll("-", "_");
|
|
3666
3680
|
const node = input(field);
|
|
3667
3681
|
const value = key.startsWith("show_") ? node.checked
|
|
3668
3682
|
: key === "organization" || node.value === "" ? node.value : Number(node.value);
|
|
3669
|
-
settings.progress_card_settings = { ...
|
|
3683
|
+
settings.progress_card_settings = { ...progress, [key]: value };
|
|
3670
3684
|
}
|
|
3671
3685
|
}
|
|
3672
3686
|
|
|
@@ -4604,8 +4618,9 @@ async function refresh(tab, cursor = undefined) {
|
|
|
4604
4618
|
if (tab === "schedules" && await loadSchedules(cursor) === false) return false;
|
|
4605
4619
|
if (tab === "defaults") await loadDefaults();
|
|
4606
4620
|
if (tab === "system") {
|
|
4607
|
-
const results = await Promise.all([window.NetizenIdentity.loadUsers(), window.NetizenSessionAccess?.load()
|
|
4608
|
-
|
|
4621
|
+
const results = await Promise.all([window.NetizenIdentity.loadUsers(), window.NetizenSessionAccess?.load(),
|
|
4622
|
+
window.NetizenProgressCard?.load()]);
|
|
4623
|
+
if (results.includes(false)) return false;
|
|
4609
4624
|
}
|
|
4610
4625
|
if (state.authExpired) return false;
|
|
4611
4626
|
if (isCurrentView()) setStatus("已更新。");
|
|
@@ -4643,7 +4658,7 @@ function selectSystemTab(name) {
|
|
|
4643
4658
|
if (state.authExpired || state.systemTab === name) return;
|
|
4644
4659
|
window.NetizenSelect?.close();
|
|
4645
4660
|
if (state.systemTab === "admins") window.NetizenIdentity?.suspendSelector();
|
|
4646
|
-
else window.NetizenSessionAccess?.closePickers();
|
|
4661
|
+
else if (state.systemTab === "access") window.NetizenSessionAccess?.closePickers();
|
|
4647
4662
|
state.systemTab = name;
|
|
4648
4663
|
for (const button of document.querySelectorAll("[data-system-tab]")) {
|
|
4649
4664
|
const selected = button.dataset.systemTab === name;
|
|
@@ -4710,8 +4725,10 @@ for (const tab of document.querySelectorAll("[data-system-tab]")) {
|
|
|
4710
4725
|
tab.addEventListener("keydown", (event) => {
|
|
4711
4726
|
if (!["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) return;
|
|
4712
4727
|
event.preventDefault();
|
|
4713
|
-
const
|
|
4714
|
-
|
|
4728
|
+
const names = [...document.querySelectorAll("[data-system-tab]")].map((button) => button.dataset.systemTab);
|
|
4729
|
+
const index = names.indexOf(tab.dataset.systemTab);
|
|
4730
|
+
const name = event.key === "Home" ? names[0] : event.key === "End" ? names.at(-1)
|
|
4731
|
+
: names[(index + (event.key === "ArrowRight" ? 1 : names.length - 1)) % names.length];
|
|
4715
4732
|
selectSystemTab(name);
|
|
4716
4733
|
document.querySelector(`#system-tab-${name}`).focus();
|
|
4717
4734
|
});
|
|
@@ -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>
|
|
@@ -488,6 +491,7 @@
|
|
|
488
491
|
<div class="session-tabs system-tabs" role="tablist" aria-label="系统管理">
|
|
489
492
|
<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
493
|
<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>
|
|
494
|
+
<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
495
|
</div>
|
|
492
496
|
<div id="system-admins" class="system-tab-panel" role="tabpanel" aria-labelledby="system-tab-admins">
|
|
493
497
|
<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 +545,34 @@
|
|
|
541
545
|
</div>
|
|
542
546
|
</form>
|
|
543
547
|
</div>
|
|
548
|
+
<div id="system-progress" class="system-tab-panel" role="tabpanel" aria-labelledby="system-tab-progress" hidden>
|
|
549
|
+
<h3>全局过程卡配置</h3>
|
|
550
|
+
<p class="defaults-help">仅在本实例的会话未单独配置过程卡时使用,不覆盖会话及聊天默认配置中已有的过程卡设置。</p>
|
|
551
|
+
<form id="global-card-form" class="card-form global-card-form">
|
|
552
|
+
<fieldset id="global-card-fields" disabled>
|
|
553
|
+
<div id="global-card-progress-settings" class="progress-settings" hidden>
|
|
554
|
+
<label>过程卡组织方式<select id="global-card-progress-organization"><option value="content">按内容</option><option value="time">按时间</option></select></label>
|
|
555
|
+
<p class="session-settings-help">按时间交错显示进展与操作,任务清单固定在底部。执行状态和异常提示始终保留。</p>
|
|
556
|
+
<div class="defaults-feedback"><label><input id="global-card-progress-show-commentary" type="checkbox">最近进展</label></div>
|
|
557
|
+
<div id="global-card-progress-commentary-capacity" class="schedule-form-grid">
|
|
558
|
+
<label>进展条数(1–8)<input id="global-card-progress-commentary-limit" type="number" min="1" max="8" step="1" required></label>
|
|
559
|
+
<label>进展摘要长度(1–320 字符)<input id="global-card-progress-commentary-max-chars" type="number" min="1" max="320" step="1" required></label>
|
|
560
|
+
</div>
|
|
561
|
+
<div class="defaults-feedback"><label><input id="global-card-progress-show-operations" type="checkbox">最近操作</label></div>
|
|
562
|
+
<div id="global-card-progress-operation-capacity" class="schedule-form-grid">
|
|
563
|
+
<label>操作条数(1–16)<input id="global-card-progress-operation-limit" type="number" min="1" max="16" step="1" required></label>
|
|
564
|
+
<label>操作摘要长度(1–240 字符)<input id="global-card-progress-operation-max-chars" type="number" min="1" max="240" step="1" required></label>
|
|
565
|
+
</div>
|
|
566
|
+
<div class="defaults-feedback"><label><input id="global-card-progress-show-plan" type="checkbox">任务清单</label></div>
|
|
567
|
+
</div>
|
|
568
|
+
<p id="global-card-progress-error" class="progress-settings-error" role="status" hidden></p>
|
|
569
|
+
</fieldset>
|
|
570
|
+
<div class="session-access-footer">
|
|
571
|
+
<p id="global-card-note" class="defaults-field-help" role="status"></p>
|
|
572
|
+
<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>
|
|
573
|
+
</div>
|
|
574
|
+
</form>
|
|
575
|
+
</div>
|
|
544
576
|
</section>
|
|
545
577
|
<section id="updates" class="panel" aria-labelledby="updates-heading" hidden>
|
|
546
578
|
<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,
|
|
@@ -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 = 19
|
|
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.v19 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
|
|
|
@@ -453,10 +453,9 @@ def _restore_settings_draft(
|
|
|
453
453
|
# /new redraws start from defaults; both toggle choices must keep
|
|
454
454
|
# the presentation settings already carried by this draft.
|
|
455
455
|
_, settings = _decode_progress_card_reference(value, element["name"])
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
option["value"] = _progress_card_reference(enabled, settings)
|
|
456
|
+
for option in element["options"]:
|
|
457
|
+
enabled, _ = _decode_progress_card_reference(option["value"], element["name"])
|
|
458
|
+
option["value"] = _progress_card_reference(enabled, settings)
|
|
460
459
|
if not any(option["value"] == value for option in element["options"]):
|
|
461
460
|
label = "保留已选值(当前不可用)"
|
|
462
461
|
if element["name"].endswith("_model"):
|
|
@@ -806,22 +805,28 @@ def _task_feedback_form_elements(
|
|
|
806
805
|
]
|
|
807
806
|
|
|
808
807
|
|
|
809
|
-
def _progress_card_reference(enabled: bool, settings: ProgressCardSettings) -> str:
|
|
808
|
+
def _progress_card_reference(enabled: bool, settings: ProgressCardSettings | None) -> str:
|
|
810
809
|
# Ordinary Feishu forms only edit the existing toggle. Carry the Admin
|
|
811
810
|
# presentation choices with both options, without a card session or new UI.
|
|
812
|
-
values =
|
|
811
|
+
values = (
|
|
812
|
+
[enabled, None] if settings is None else
|
|
813
|
+
[enabled, *(getattr(settings, name) for name in _PROGRESS_CARD_FIELDS)]
|
|
814
|
+
)
|
|
813
815
|
return _PROGRESS_CARD_REFERENCE_PREFIX + json.dumps(values, separators=(",", ":"))
|
|
814
816
|
|
|
815
817
|
|
|
816
818
|
def _decode_progress_card_reference(value: Any, field: str) -> tuple[bool, ProgressCardSettings | None]:
|
|
817
819
|
value = _bounded_string(value, field, max_chars=128)
|
|
818
820
|
if not value.startswith(_PROGRESS_CARD_REFERENCE_PREFIX):
|
|
819
|
-
return _decode_task_feedback_reference(value, field),
|
|
821
|
+
return _decode_task_feedback_reference(value, field), ProgressCardSettings()
|
|
820
822
|
try:
|
|
821
823
|
values = json.loads(value[len(_PROGRESS_CARD_REFERENCE_PREFIX):])
|
|
822
|
-
if not isinstance(values, list) or
|
|
824
|
+
if not isinstance(values, list) or not values or type(values[0]) is not bool:
|
|
823
825
|
raise ValueError("invalid progress card reference")
|
|
824
|
-
settings =
|
|
826
|
+
settings = (
|
|
827
|
+
None if values[1:] == [None] else
|
|
828
|
+
ProgressCardSettings.from_dict(dict(zip(_PROGRESS_CARD_FIELDS, values[1:], strict=True)))
|
|
829
|
+
)
|
|
825
830
|
except (ValueError, TypeError) as error:
|
|
826
831
|
raise CardActionError("过程卡设置无效,请重新打开配置卡片。") from error
|
|
827
832
|
return values[0], settings
|
|
@@ -834,7 +839,7 @@ def _decode_task_feedback_fields(payload: Mapping[str, Any], *, prefix: str) ->
|
|
|
834
839
|
_decode_task_feedback_reference(payload[f"{prefix}_task_reactions"], f"{prefix}_task_reactions"),
|
|
835
840
|
progress_enabled,
|
|
836
841
|
_decode_task_feedback_reference(payload[f"{prefix}_completion_mention"], f"{prefix}_completion_mention"),
|
|
837
|
-
settings
|
|
842
|
+
settings,
|
|
838
843
|
)
|
|
839
844
|
|
|
840
845
|
|
|
@@ -267,7 +267,6 @@ from .prompt_projection import (
|
|
|
267
267
|
project_current_message,
|
|
268
268
|
)
|
|
269
269
|
from .projects import ProjectError, ProjectRegistry, UnknownProject
|
|
270
|
-
from .progress_card_settings import ProgressCardSettings
|
|
271
270
|
from .task_text import project_task_text
|
|
272
271
|
from .result_images import prepare_result_images
|
|
273
272
|
from .quoted_context import (
|
|
@@ -5144,7 +5143,7 @@ class ChannelApplication:
|
|
|
5144
5143
|
reaction_pulse_enabled=bool(intent.reaction_pulse_enabled),
|
|
5145
5144
|
progress_card_enabled=bool(intent.progress_card_enabled),
|
|
5146
5145
|
completion_mention_enabled=bool(intent.completion_mention_enabled),
|
|
5147
|
-
progress_card_settings=intent.progress_card_settings
|
|
5146
|
+
progress_card_settings=intent.progress_card_settings,
|
|
5148
5147
|
)
|
|
5149
5148
|
project, binding = await self._create_binding(
|
|
5150
5149
|
scope=intent.scope,
|