kenaz 0.3.22 → 0.3.23
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.
- package/core/.claude/hooks/_user-scope.js +1 -1
- package/core/.claude/hooks/core-resolve.js +1 -1
- package/core/.claude/hooks/worktree-create.js +6 -6
- package/core/.claude/hooks/worktree-remove.js +4 -4
- package/core/.collaboration/core/reconcile.js +16 -1
- package/core/.collaboration/core/task-2467-lifecycle.test.js +63 -0
- package/core/.collaboration/core/task-api.js +37 -7
- package/core/.formation/bifrost/launch.js +1 -1
- package/core/.formation/tools/kenaz-stats.js +1 -1
- package/core/.formation/tools/post-complete/git-merge.js +1 -1
- package/core/.formation/tools/prompt.js +1 -1
- package/core/.kenaz/specialist/ansuz_rules.yaml +7 -51
- package/core/.kenaz/specialist/ansuz_session_handoff.schema.json +2 -6
- package/core/.rule/general/project-self-containment.yaml +2 -2
- package/core/.specialist/Amelia/README.md +1 -1
- package/core/.specialist/Amelia/rule.yaml +1 -1
- package/core/.specialist/Ansuz/RULES.md +1 -1
- package/core/.specialist/Ansuz/concepts/commitment_layer.yaml +1 -1
- package/core/.specialist/Ansuz/concepts/evolvable_guardrails.yaml +1 -1
- package/core/.specialist/Ansuz/knowledge.yaml +1 -3
- package/core/.specialist/tools/__tests__/task-2409-lessons.test.js +10 -0
- package/core/.specialist/tools/__tests__/task-2427-harvest.test.js +25 -0
- package/core/.specialist/tools/ansuz-boot-fast.js +1 -1
- package/core/.specialist/tools/failure-detector.js +4 -4
- package/core/.specialist/tools/handoff-doc.js +1 -1
- package/core/.specialist/tools/lessons.js +2 -2
- package/core/CLAUDE.md +5 -5
- package/core/KENAZ_CORE_VERSION +1 -1
- package/core/dashboard/scripts/install-kenaz-cli.js +21 -6
- package/core/dev/scripts/check-file-size.js +1 -1
- package/core/dev/scripts/ci-feedback.js +1 -1
- package/core/dev/scripts/gc-agent-worktrees.js +11 -11
- package/core/dev/scripts/kenaz-session.js +3 -3
- package/core/dev/scripts/peer-identity-e2e.js +3 -3
- package/core/dev/scripts/run-rust-tests.js +2 -2
- package/core/dev/scripts/skill-routing-replay.js +3 -3
- package/core/dev/scripts/task1961/selftest.js +2 -2
- package/core/dev/scripts/windows-hide-guard.test.js +97 -0
- package/core/plugins/kenaz/guidance.md +1 -0
- package/core/plugins/kenaz/hooks/core-resolve.js +1 -1
- package/core/plugins/kenaz/hooks/kenaz-hook.js +52 -4
- package/core/plugins/kenaz/scripts/kenaz.test.js +72 -5
- package/lib/cli.js +9 -5
- package/package.json +6 -6
- package/vendor/install-kenaz-cli.js +21 -6
- package/core/.kenaz/designs/METAPLASTICITY_CONFIDENCE_DESIGN.md +0 -537
- package/core/.kenaz/designs/REFLEX_INITIATOR_DESIGN.md +0 -501
- package/core/.kenaz/designs/TASK_1385_handoff_mcp_design.md +0 -426
- package/core/.kenaz/designs/TASK_932_hippocampus_consolidation.md +0 -103
- package/core/.kenaz/designs/TASK_934_efe_signal_engine.md +0 -97
- package/core/.kenaz/designs/TASK_935_self_evolution_framework.md +0 -154
- package/core/.kenaz/designs/VISION_cognitive_architecture_roadmap.md +0 -159
- package/core/.kenaz/designs/metaplasticity_simulation_results.json +0 -696
- package/core/.kenaz/main-memory/README.md +0 -230
- package/core/.kenaz/main-memory/kenaz/cortex/001_cortex_overview.md +0 -168
- package/core/.kenaz/main-memory/kenaz/cortex/001_rag_engine_overview.md +0 -30
- package/core/.kenaz/main-memory/kenaz/memory-system/001_three_tier_architecture.md +0 -361
- package/core/.kenaz/main-memory/kenaz/pipeline/001_task_execution_flow.md +0 -117
- package/core/.kenaz/main-memory/kenaz/pipeline/001_task_granularity.md +0 -154
- package/core/.kenaz/main-memory/kenaz/pipeline/002_team_priority.md +0 -51
- package/core/.kenaz/main-memory/kenaz/pipeline/003_feature_id_system.md +0 -46
- package/core/.kenaz/main-memory/kenaz/rules/001_gen_007_self_containment.md +0 -108
- package/core/.kenaz/main-memory/kenaz/rules/001_rule_priority_system.md +0 -121
- package/core/.kenaz/main-memory/kenaz/rules/002_agt_006_pre_check.md +0 -0
- package/core/.kenaz/main-memory/kenaz/rules/003_ppl_002_task_archival.md +0 -48
- package/core/.kenaz/main-memory/kenaz/system/001_dual_track_task_system.md +0 -197
- package/core/.kenaz/main-memory/knowledge/patterns/001_json_bom_issue.md +0 -78
- package/core/.kenaz/main-memory/knowledge/patterns/001_leader_worker_pattern.md +0 -0
- package/core/.kenaz/main-memory/knowledge/patterns/002_scope_path_conflict.md +0 -115
- package/core/.kenaz/main-memory/knowledge/patterns/002_task_dependency_resolution.md +0 -223
- package/core/.kenaz/main-memory/knowledge/patterns/003_question_protocol.md +0 -242
- package/core/.kenaz/main-memory/knowledge/patterns/004_user_insight_value.md +0 -111
- package/core/.kenaz/main-memory/knowledge/patterns/005_file_lock_pattern.md +0 -274
- package/core/.kenaz/main-memory/knowledge/references/001_ppl_rules.md +0 -28
- package/core/.kenaz/main-memory/knowledge/solutions/001_json_bom_issue.md +0 -137
- package/core/.kenaz/main-memory/knowledge/solutions/001_team_invocation.md +0 -0
- package/core/.kenaz/main-memory/knowledge/solutions/002_passive_monitoring.md +0 -0
- package/core/.kenaz/main-memory/knowledge/solutions/003_windows_file_race_condition.md +0 -239
- package/core/.kenaz/main-memory/registry.json +0 -326
- package/core/.kenaz/main-memory/version.yaml +0 -58
- package/core/.kenaz/specialist/memory_guard_fired.json +0 -1
- package/core/.kenaz/specialist/memory_guard_trigger_cache.json +0 -1
- package/core/.kenaz/specialist/memory_source_priority.yaml +0 -260
- package/core/.kenaz/specialist/prompt_1775.txt +0 -317
- package/core/.kenaz/specialist/prompt_1776.txt +0 -326
- package/core/.kenaz/specialist/prompt_1791.txt +0 -320
- package/core/.kenaz/specialist/prompt_1792.txt +0 -320
- package/core/.kenaz/specialist/prompt_1795.txt +0 -281
- package/core/.kenaz/specialist/prompt_1813.txt +0 -332
- package/core/.kenaz/specialist/prompt_1814.txt +0 -401
- package/core/.kenaz/specialist/prompt_1815.txt +0 -394
- package/core/.kenaz/specialist/prompt_1816.txt +0 -437
- package/core/.kenaz/specialist/prompt_1818.txt +0 -361
- package/core/.kenaz/specialist/prompt_1819.txt +0 -421
- package/core/.kenaz/specialist/prompt_1821.txt +0 -345
- package/core/.kenaz/specialist/prompt_1822.txt +0 -313
- package/core/.kenaz/specialist/prompt_1824.txt +0 -348
- package/core/.kenaz/specialist/prompt_1826.txt +0 -388
- package/core/.kenaz/specialist/rune_efe_salience_gap.md +0 -21
- package/core/.kenaz/specialist/task1825_update.json +0 -43
- package/core/.kenaz/specialist/taskgen/consolidation_i.json +0 -38
- package/core/.kenaz/specialist/taskgen/csharp_a.json +0 -44
- package/core/.kenaz/specialist/taskgen/csharp_b.json +0 -40
- package/core/.kenaz/specialist/taskgen/embedding_e.json +0 -34
- package/core/.kenaz/specialist/taskgen/hygiene_fg.json +0 -39
- package/core/.kenaz/specialist/taskgen/pathology_h.json +0 -36
- package/core/.kenaz/specialist/taskgen/unity_noise_d.json +0 -38
- package/core/.kenaz/specialist/taskgen/visibility_c.json +0 -38
- package/core/.specialist/Ansuz/decisions/ADR-requirement-graph-layer.md +0 -390
- package/core/.specialist/Ansuz/self_model_seed.backup.json +0 -100
- package/core/.specialist/ansuz_session_handoff.json +0 -96
- package/core/dev/ALAYA_FIELD_FEEDBACK_DESIGN.md +0 -126
- package/core/dev/ANSUZ_SCAFFOLD_DIET_2026-09-20.md +0 -231
- package/core/dev/ANSUZ_STARTUP_INJECTION_REVIEW.md +0 -355
- package/core/dev/ANSUZ_WORKFLOW_MODERNIZATION.md +0 -143
- package/core/dev/CORTEX_META_GRAPH_ASSESSMENT.md +0 -99
- package/core/dev/FREYA_DOWNSTREAM_BUGS_2026-09-19.md +0 -44
- package/core/dev/GLOBAL_MEMORY_IDENTITY_CONSOLIDATION.md +0 -263
- package/core/dev/GUARD_EFFECTIVENESS_DESIGN.md +0 -180
- package/core/dev/HEALTH_GATE_VARIANCE_ASSESSMENT.md +0 -271
- package/core/dev/HOOK_DIET_2026-09-21.md +0 -126
- package/core/dev/JEV_INTEGRATION_PLAN.md +0 -189
- package/core/dev/KENAZ_AGENT_CONNECT_v1_SPEC.md +0 -139
- package/core/dev/MOBILE_DESIGN_SPEC.md +0 -569
- package/core/dev/MULTI_ANSUZ_SPEC.md +0 -136
- package/core/dev/MUNINN_RETIREMENT.md +0 -115
- package/core/dev/PHASE3_ATTRIBUTION_POPULATION_DIAGNOSIS.md +0 -211
- package/core/dev/PHASE3_P3-2B_TASKLEVEL_PROBE.md +0 -83
- package/core/dev/PHASE3_P3-2_POPULATION_DISJOINTNESS.md +0 -83
- package/core/dev/PHASE3_P3-2_REMEASURE_REPORT.md +0 -231
- package/core/dev/PREDICTION_GROUNDING_DESIGN.md +0 -376
- package/core/dev/PRODUCT_SPEC.md +0 -317
- package/core/dev/PROJECT_REGISTRY_DUPLICATE_ASSESSMENT.md +0 -86
- package/core/dev/STARTUP_TIMELINE_TASK_1995.md +0 -181
- package/core/dev/SYNAPSE_WORKER_PER_PROJECT.md +0 -881
- package/core/dev/TASK_1680_P3-3_DISPATCH_SPEC.md +0 -96
- package/core/dev/TASK_1684_CALIBRATION_IMPACT_ANALYSIS.md +0 -170
- package/core/dev/TASK_1684_FORK_A_GOODHART_DESIGN.md +0 -171
- package/core/dev/TASK_1684_P3_2_REMEASURE_VALIDATION.md +0 -262
- package/core/dev/TASK_1903_SIGNAL_AUC_MEASUREMENT.md +0 -207
- package/core/dev/TASK_1904_BRANCH_INTEGRITY_AUDIT.md +0 -146
- package/core/dev/ansuz-eval/README.md +0 -38
- package/core/dev/ansuz-eval/build-fixtures.js +0 -87
- package/core/dev/ansuz-eval/grade.js +0 -96
- package/core/dev/ansuz-eval/grader.test.js +0 -117
- package/core/dev/ansuz-eval/tasks.md +0 -32
- package/core/dev/archive/ansuz/BOOT_FULL.md +0 -141
- package/core/dev/archive/ansuz/agents/ansuz-boot.md +0 -176
- package/core/dev/archive/ansuz/designs/alaya-passive-surfacing.md +0 -84
- package/core/dev/archive/ansuz/designs/cc_memory_indexing.md +0 -307
- package/core/dev/archive/ansuz/designs/check_guard.md +0 -322
- package/core/dev/archive/ansuz/designs/consequence_loop.md +0 -227
- package/core/dev/archive/ansuz/designs/mcp_kuzudb_lock_architecture.md +0 -312
- package/core/dev/archive/ansuz/designs/phase0_git_enrichment.md +0 -278
- package/core/dev/archive/ansuz/designs/refactor_mcp_tools_synapse.md +0 -490
- package/core/dev/archive/ansuz/designs/semantic_markdown_extraction.md +0 -167
- package/core/dev/archive/ansuz/designs/task_1372_prompt_injects_into.md +0 -193
- package/core/dev/archive/ansuz/designs/thought_stack.md +0 -286
- package/core/dev/archive/ansuz/investigations/reachability_unified_api_2026-04-11.md +0 -330
- package/core/dev/archive/ansuz/investigations/synapse_orphans_indexing_bug_2026-04-11.md +0 -352
- package/core/dev/archive/ansuz/investigations/synapse_orphans_reindex_verification_2026-04-11.md +0 -48
- package/core/dev/archive/ansuz/investigations/synapse_orphans_verification_2026-04-11.md +0 -170
- package/core/dev/archive/ansuz/legacy/kernel.yaml +0 -399
- package/core/dev/archive/ansuz/legacy/phases/phase_0.yaml +0 -418
- package/core/dev/archive/ansuz/legacy/phases/phase_1.yaml +0 -376
- package/core/dev/archive/ansuz/legacy/phases/phase_10.yaml +0 -35
- package/core/dev/archive/ansuz/legacy/phases/phase_11.yaml +0 -582
- package/core/dev/archive/ansuz/legacy/phases/phase_2.yaml +0 -94
- package/core/dev/archive/ansuz/legacy/phases/phase_3.yaml +0 -274
- package/core/dev/archive/ansuz/legacy/phases/phase_4.yaml +0 -67
- package/core/dev/archive/ansuz/legacy/phases/phase_5.yaml +0 -32
- package/core/dev/archive/ansuz/legacy/phases/phase_6.yaml +0 -91
- package/core/dev/archive/ansuz/legacy/phases/phase_7.yaml +0 -58
- package/core/dev/archive/ansuz/legacy/phases/phase_8.yaml +0 -146
- package/core/dev/archive/ansuz/legacy/phases/phase_9.yaml +0 -424
- package/core/dev/archive/ansuz/specs/INDEX_bifrost_hook_parity.yaml +0 -92
- package/core/dev/archive/ansuz/specs/active-inference-formation.yaml +0 -453
- package/core/dev/archive/ansuz/specs/brief_TASK_1228_userpromptsubmit.yaml +0 -191
- package/core/dev/archive/ansuz/specs/brief_TASK_1229_pretooluse_posttooluse.yaml +0 -250
- package/core/dev/archive/ansuz/specs/brief_TASK_1230_sessionstart_stop.yaml +0 -301
- package/core/dev/archive/ansuz/specs/brief_TASK_1231_verification.yaml +0 -272
- package/core/dev/archive/skills/feature_agent/SKILL.md +0 -289
- package/core/dev/design/PHASE4_DESIGN.md +0 -559
- package/core/dev/design/dashboard_docs_integration_PLAN.md +0 -388
- package/core/dev/design/matrix_format_ABBREVIATIONS.md +0 -655
- package/core/dev/design/matrix_format_DESIGN_SPEC.md +0 -601
- package/core/dev/design/matrix_format_DISCUSSION_SUMMARY.md +0 -484
- package/core/dev/design/matrix_format_EXAMPLE_memory.matrix +0 -13
- package/core/dev/design/matrix_format_EXAMPLE_project_status.matrix +0 -9
- package/core/dev/design/matrix_format_EXAMPLE_tasks.matrix +0 -14
- package/core/dev/design/matrix_format_SYNTAX_BNF.md +0 -754
- package/core/dev/design/matrix_format_TOKEN_COMPARISON.md +0 -484
- package/core/dev/design/matrix_v2_COGNITIVE_DESIGN.md +0 -503
- package/core/dev/design/matrix_v2_DISCUSSION_SUMMARY.md +0 -414
- package/core/dev/design/matrix_v2_EXAMPLE.matrix +0 -67
- package/core/dev/designs/EXPANDABLE_CARD_DESIGN_SPEC.md +0 -509
- package/core/dev/jev-eval/ACTIVE_CORRECTION.md +0 -52
- package/core/dev/jev-eval/ANNOTATION_GUIDE.md +0 -68
- package/core/dev/jev-eval/BASELINE_COMPARISON.md +0 -45
- package/core/dev/jev-eval/CONTEXT_REVIEW.md +0 -31
- package/core/dev/jev-eval/EVALUATION_STATUS.md +0 -39
- package/core/dev/jev-eval/HISTORICAL_CORPUS.md +0 -33
- package/core/dev/jev-eval/PACKAGING_VERIFICATION.md +0 -42
- package/core/dev/jev-eval/README.md +0 -101
- package/core/dev/jev-eval/THALAMUS_RANKING.md +0 -58
- package/core/dev/jev-eval/VALIDATION_PROGRESS.md +0 -54
- package/core/dev/jev-eval/cli.mjs +0 -50
- package/core/dev/jev-eval/context.mjs +0 -183
- package/core/dev/jev-eval/corpus.mjs +0 -186
- package/core/dev/jev-eval/fixtures/conversation-review.seed.jsonl +0 -6
- package/core/dev/jev-eval/fixtures/synthetic.jsonl +0 -11
- package/core/dev/jev-eval/metrics.mjs +0 -67
- package/core/dev/jev-eval/muninn-baseline.mjs +0 -119
- package/core/dev/jev-eval/providers.mjs +0 -95
- package/core/dev/jev-eval/reports/annotation-pilot-2026-09-20.json +0 -32
- package/core/dev/jev-eval/reports/context-review-2026-09-20.json +0 -48
- package/core/dev/jev-eval/reports/conversation-review.pending.json +0 -151
- package/core/dev/jev-eval/reports/history-corpus-2026-09-20.json +0 -52
- package/core/dev/jev-eval/reports/length-probe-2026-09-20.json +0 -133
- package/core/dev/jev-eval/reports/live-smoke-2026-09-20.json +0 -616
- package/core/dev/jev-eval/reports/muninn-baseline-2026-09-20.json +0 -52
- package/core/dev/jev-eval/reports/resilience-2026-09-20.json +0 -520
- package/core/dev/jev-eval/reports/rules-baseline.json +0 -197
- package/core/dev/jev-eval/reports/synthetic-review.pending.json +0 -357
- package/core/dev/jev-eval/resilience.mjs +0 -71
- package/core/dev/jev-eval/review.mjs +0 -78
- package/core/dev/jev-eval/schema.mjs +0 -87
- package/core/dev/jev-eval/test/context.test.mjs +0 -95
- package/core/dev/jev-eval/test/corpus.test.mjs +0 -102
- package/core/dev/jev-eval/test/eval.test.mjs +0 -146
- package/core/dev/jev-eval/test/muninn-baseline.test.mjs +0 -71
- package/core/dev/jev-eval/test/resilience.test.mjs +0 -72
- package/core/dev/jev-eval/test/review.test.mjs +0 -61
- package/core/dev/pipeline/PHASE3_PLANNING_SUMMARY.md +0 -338
- package/core/dev/pipeline/PROGRESS.md +0 -113
- package/core/dev/pipeline/PROGRESS_template.md +0 -860
- package/core/dev/pipeline/QA_REPORT_F008.md +0 -431
- package/core/dev/pipeline/QA_REPORT_LOCAL_CLAUDE_DIAGNOSIS.md +0 -583
- package/core/dev/pipeline/README.md +0 -210
- package/core/dev/pipeline/WORKFLOW_GUIDE.md +0 -824
- package/core/dev/pipeline/archived/TASK_015_tauri_init.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_016_tauri_commands.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_017_rust_pty.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_018_tauri_bundle.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_019_release_workflow.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_020_update_ui.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_021_update_notification_ui.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_022_remove_node_pty.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_023_api_routes_migration.yaml +0 -86
- package/core/dev/pipeline/archived/TASK_024_feature_id_system.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_025_executable_acceptance.yaml +0 -66
- package/core/dev/pipeline/archived/TASK_026_spec_versioning.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_027_drift_detection.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_028_tauri_pty_manager.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_029_tauri_pty_commands.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_030_frontend_session_adapter.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_031_terminal_tauri_events.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_041_scheduler_data_models.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_042_path_lock_manager.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_043_process_manager.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_044_git_integration.yaml +0 -85
- package/core/dev/pipeline/archived/TASK_045_task_queue_manager.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_046_scheduler_dispatcher.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_047_tauri_scheduler_commands.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_048_realtime_status_push.yaml +0 -92
- package/core/dev/pipeline/archived/TASK_049_frontend_scheduler_integration.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_050_error_recovery.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_051_optimization_proposals_backend.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_052_optimization_proposals_ui.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_053_optimization_proposals_diff_view.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_054_multi_project_scheduler_state.yaml +0 -76
- package/core/dev/pipeline/archived/TASK_055_scheduler_api_project_scope.yaml +0 -64
- package/core/dev/pipeline/archived/TASK_056_frontend_scheduler_project_scope.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_057_scheduler_module_structure.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_058_scheduler_models_extract.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_059_scheduler_core_extract.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_060_scheduler_commands_extract.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_061_scheduler_specialized_commands.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_062_process_manager_module_structure.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_063_process_manager_core_extract.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_064_recovery_module_structure.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_065_recovery_core_extract.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_066_self_enhancement_scheduler_models.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_067_agents_section_quick_actions.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_067_self_enhancement_scheduler_core.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_068_agent_workflow_rule_enhancement.yaml +0 -46
- package/core/dev/pipeline/archived/TASK_068_self_enhancement_tauri_commands.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_069_agent_wizard_responsive.yaml +0 -46
- package/core/dev/pipeline/archived/TASK_069_self_enhancement_ui.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_070_preview_panel_redesign.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_070_self_enhancement_integration.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_071_preview_panel_qa.yaml +0 -98
- package/core/dev/pipeline/archived/TASK_071_single_agent_config.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_072_preview_modal_esc_fix.yaml +0 -71
- package/core/dev/pipeline/archived/TASK_072_product_review_module.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_073_agents_page_component_refactor.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_073_rename_single_agent.yaml +0 -64
- package/core/dev/pipeline/archived/TASK_074_preview_mode_ui_diagnosis.yaml +0 -71
- package/core/dev/pipeline/archived/TASK_074_single_agent_ui_toggle.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_075_agents_page_component_refactor.yaml +0 -69
- package/core/dev/pipeline/archived/TASK_075_single_agent_integration_test.yaml +0 -75
- package/core/dev/pipeline/archived/TASK_076_preview_mode_ui_diagnosis.yaml +0 -70
- package/core/dev/pipeline/archived/TASK_076_single_agent_continuous_mode.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_077_failure_directory_structure.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_077_single_agent_typescript_types.yaml +0 -59
- package/core/dev/pipeline/archived/TASK_078_fail_001_agent_no_output.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_078_single_agent_ui_simplify.yaml +0 -74
- package/core/dev/pipeline/archived/TASK_079_dashboard_rwd_responsive.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_079_fail_002_json_bom.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_080_fail_003_queue_pollution.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_080_http_server_module.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_081_failure_logging_tools.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_081_http_api_routes.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_082_frontend_api_adapter.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_082_integrate_failure_to_workflow.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_083_cleanup_nextjs_api.yaml +0 -48
- package/core/dev/pipeline/archived/TASK_083_task_queue_cleanup.yaml +0 -67
- package/core/dev/pipeline/archived/TASK_084_rust_dead_code_cleanup.yaml +0 -66
- package/core/dev/pipeline/archived/TASK_084_scheduler_sync_logic_fix.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_085_http_api_web_mode_fixes.yaml +0 -46
- package/core/dev/pipeline/archived/TASK_085_memory_consolidation_0204_0205.yaml +0 -98
- package/core/dev/pipeline/archived/TASK_086_collapsible_preview_panel.yaml +0 -161
- package/core/dev/pipeline/archived/TASK_086_web_mode_feature_parity.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_087_manual_memory_archival.yaml +0 -163
- package/core/dev/pipeline/archived/TASK_087_mobile_http_control.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_088_fail_003_to_ppl_002_rule.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_088_mobile_http_qa.yaml +0 -121
- package/core/dev/pipeline/archived/TASK_089_agent_collaboration_topic.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_089_web_mode_monitor_fix.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_090_cli_detection_fix.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_090_ui_ux_lessons_topic.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_091_expandable_card_design.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_091_move_agent_section_components.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_092_expandable_card_component.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_092_refactor_agent_create_wizard.yaml +0 -84
- package/core/dev/pipeline/archived/TASK_093_taskcard_detail_integration.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_093_update_barrel_exports_test.yaml +0 -84
- package/core/dev/pipeline/archived/TASK_094_ai_agent_generation_enhancement.yaml +0 -115
- package/core/dev/pipeline/archived/TASK_094_proposalcard_detail_integration.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_095_preview_fixes.yaml +0 -129
- package/core/dev/pipeline/archived/TASK_095_single_agent_task_selector.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_096_agents_page_ux_improvements.yaml +0 -163
- package/core/dev/pipeline/archived/TASK_096_single_agent_status_sync.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_097_local_claude_error_logging.yaml +0 -59
- package/core/dev/pipeline/archived/TASK_097_single_agent_monitor_events.yaml +0 -59
- package/core/dev/pipeline/archived/TASK_098_product_manager_team_phase2.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_098_single_agent_refactor_test.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_099_backend_team_creation.yaml +0 -258
- package/core/dev/pipeline/archived/TASK_100_frontend_team_creation.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_101_orchestrator_system.yaml +0 -403
- package/core/dev/pipeline/archived/TASK_102_designer_sre_teams.yaml +0 -90
- package/core/dev/pipeline/archived/TASK_103_integration_testing.yaml +0 -86
- package/core/dev/pipeline/archived/TASK_128_integration_testing.yaml +0 -83
- package/core/dev/pipeline/archived/TASK_134_cortex_v2_phase3_file_watcher.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_134_team_http_api.yaml +0 -96
- package/core/dev/pipeline/archived/TASK_135_cortex_v2_phase3_git_monitor.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_136_cortex_v2_phase3_change_analyzer.yaml +0 -69
- package/core/dev/pipeline/archived/TASK_137_cortex_v2_phase3_cache_invalidator.yaml +0 -67
- package/core/dev/pipeline/archived/TASK_137_team_orchestrator_integration.yaml +0 -93
- package/core/dev/pipeline/archived/TASK_138_cortex_v2_phase3_distributed_cache.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_138_matrix_folder_structure.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_139_cortex_v2_phase3_cache_prewarming.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_146_unified_documentation.yaml +0 -141
- package/core/dev/pipeline/archived/TASK_147_pipeline_execution_rules.yaml +0 -76
- package/core/dev/pipeline/archived/TASK_148_update_claude_md.yaml +0 -77
- package/core/dev/pipeline/archived/TASK_149_fix_nextjs_mdx_serialization.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_149_update_team_docs.yaml +0 -77
- package/core/dev/pipeline/archived/TASK_150_pipeline_workflow_guide.yaml +0 -82
- package/core/dev/pipeline/archived/TASK_164_fix_smart_context_switch.yaml +0 -49
- package/core/dev/pipeline/archived/TASK_165_ctags_symbol_index.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_166_symbol_search_mcp_tool.yaml +0 -48
- package/core/dev/pipeline/archived/TASK_167_llm_module_summary.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_168_map_reduce_context.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_169_v2_integration_testing.yaml +0 -52
- package/core/dev/pipeline/backups/archive_2026-02-04T22-07-22/TASK_QUEUE_backup.json +0 -95
- package/core/dev/pipeline/docs/multi-agent-coordination.md +0 -446
- package/core/dev/pipeline/docs/overview.md +0 -406
- package/core/dev/pipeline/docs/task-management.md +0 -412
- package/core/dev/pipeline/docs/workflows.md +0 -32
- package/core/dev/pipeline/orchestrator/schemas/task_queue_schema.json +0 -58
- package/core/dev/pipeline/orchestrator/schemas/task_schema.json +0 -139
- package/core/dev/pipeline/plans/PLAN_task_cli_refactor.md +0 -281
- package/core/dev/pipeline/test_results/TASK_TEST_PARALLEL_002_result.txt +0 -27
- package/core/dev/plans/ANSUZ_SLIM_PLAN.md +0 -68
- package/core/dev/plans/CLI_FIRST_INSTALL_FLOW.md +0 -120
- package/core/dev/plans/FORMATION_RETIREMENT_PLAN.md +0 -313
- package/core/dev/plans/KUZU_REPLACEMENT_PLAN.md +0 -126
- package/core/dev/scripts/CRASH_DIAGNOSIS.md +0 -47
- package/core/dev/scripts/README.md +0 -142
- package/core/dev/scripts/RUN_ONCE.bat +0 -40
- package/core/dev/scripts/START_DEV_AGENT.bat +0 -63
- package/core/dev/scripts/START_MULTI_AGENT.bat +0 -80
- package/core/dev/scripts/dev_agent_scheduler.ps1 +0 -536
- package/core/dev/scripts/init_git.ps1 +0 -396
- package/core/dev/scripts/init_git.sh +0 -337
- package/core/dev/scripts/init_project.ps1 +0 -851
- package/core/dev/scripts/init_project.sh +0 -477
- package/core/dev/scripts/multi_agent_scheduler.ps1 +0 -2021
- package/core/dev/scripts/multi_agent_scheduler.sh +0 -1344
- package/core/dev/scripts/run_once.sh +0 -47
- package/core/dev/scripts/setup_rag.ps1 +0 -304
- package/core/dev/scripts/setup_rag.sh +0 -230
- package/core/dev/scripts/start_dev_agent.sh +0 -137
- package/core/dev/scripts/start_multi_agent.sh +0 -41
- package/core/dev/scripts/sync_task_queue.ps1 +0 -505
- package/core/dev/scripts/sync_task_queue.sh +0 -392
- package/core/dev/specs/agent-connect/PROTOCOL.md +0 -177
- package/core/dev/specs/agent-connect/SDK_GUIDE.md +0 -915
- package/core/dev/specs/agent-connect/examples/minimal-site/README.md +0 -137
- package/core/dev/specs/agent-connect/examples/minimal-site/package.json +0 -12
- package/core/dev/specs/agent-connect/examples/minimal-site/public/index.html +0 -116
- package/core/dev/specs/agent-connect/examples/minimal-site/public/install-redirect.js +0 -73
- package/core/dev/specs/agent-connect/examples/minimal-site/server.js +0 -516
- package/core/dev/specs/agent-connect/examples/minimal-site/test/smoke.test.mjs +0 -263
- package/core/dev/specs/agent-connect/history/DEFECT_REPORT_kenaz-agent-hub_2026-09-09_v0.4-empty-prompt-no-first-turn.md +0 -77
- package/core/dev/specs/agent-connect/history/DEFECT_REPORT_kenaz-agent-hub_2026-09-09_v0.4-prompt-mojibake.md +0 -90
- package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-07.md +0 -61
- package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-08_relay-v1-conformance.md +0 -76
- package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-09_v0.4-session-channel.md +0 -87
- package/core/dev/specs/agent-connect/history/FLOWPIX_REPLY_agent-hub_2026-09-08_relay-v1-answers.md +0 -68
- package/core/dev/specs/agent-connect/history/FLOWPIX_bridge_CONTRACT.md +0 -642
- package/core/dev/specs/agent-connect/history/FLOWPIX_spikes_relay_spike_relay.mjs +0 -244
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-07.md +0 -77
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_direction-change-v0.3.md +0 -44
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_relay-v1-answers-ack.md +0 -37
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_relay-v1-conformance.md +0 -56
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_annotations-install-coldstart.md +0 -44
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_empty-prompt-first-turn.md +0 -56
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_prompt-mojibake-fixed.md +0 -48
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_session-channel.md +0 -57
- package/core/dev/specs/agent-connect/history/PROTOCOL_v0.3_snapshot.md +0 -379
- package/core/dev/specs/agent-connect/history/README.md +0 -47
- package/core/dev/specs/peer/CODEX_INTERACTIVE_PUSH.md +0 -65
- package/core/dev/specs/peer/CODEX_MANAGED_DAEMON.md +0 -54
- package/core/dev/specs/peer/CODEX_PEER_PULL_SPIKE.md +0 -54
- package/core/dev/specs/peer/MODS_SPIKE.md +0 -133
- package/core/dev/specs/peer/PER_PROJECT_ADDRESSING.md +0 -143
- package/core/dev/specs/peer/SWARM_PROTOCOLS.md +0 -256
- package/core/dev/specs/peer/codex-hook-shim-peer.test.js +0 -113
- package/core/dev/specs/peer/codex-push-launcher.test.js +0 -142
- package/core/dev/specs/peer/setup-codex-hooks.test.js +0 -60
- package/core/dev/specs/peer-ansuz/DELIVERY_SPIKE.md +0 -397
- package/core/dev/specs/peer-ansuz/DESIGN.md +0 -109
- package/core/dev/specs/peer-ansuz/spike/claude_poke.js +0 -129
- package/core/dev/specs/peer-ansuz/spike/claude_session_start_hook.js +0 -37
- package/core/dev/specs/peer-ansuz/spike/claude_settings_hook.json +0 -14
- package/core/dev/specs/peer-ansuz/spike/codex_appserver_client.js +0 -105
- package/core/dev/specs/peer-ansuz/spike/codex_appserver_query.js +0 -29
- package/core/dev/specs/peer-ansuz/spike/extract_timeline.js +0 -26
- package/core/dev/specs/synapse/SYMBOL_IDENTITY.md +0 -305
- package/core/dev/spikes/A4-cypher-varlen.md +0 -176
- package/core/dev/spikes/bloat-rounds.sh +0 -25
- package/core/dev/spikes/mods/clean-claude.js +0 -9
- package/core/dev/spikes/mods/drive-probe.js +0 -29
- package/core/dev/spikes/mods/e2e-peer.js +0 -71
- package/core/dev/spikes/mods/evidence/e2e-peer-control.json +0 -17
- package/core/dev/spikes/mods/evidence/e2e-peer-mod.json +0 -17
- package/core/dev/spikes/mods/evidence/probe-006a6e65-d807-4bc1-b648-fd7d1edfe0b4.jsonl +0 -4
- package/core/dev/spikes/mods/evidence/probe-cebdf1f7-f9c4-47a8-83cd-7c0786177404.jsonl +0 -12
- package/core/dev/spikes/mods/evidence/probe-eb21147d-10ce-4c32-93ed-37ca37d88d5a.jsonl +0 -11
- package/core/dev/spikes/mods/evidence/stream-cebdf1f7.jsonl +0 -18
- package/core/dev/spikes/mods/kenaz-mod-probe/.claude-plugin/plugin.json +0 -1
- package/core/dev/spikes/mods/kenaz-mod-probe/hooks/hooks.json +0 -1
- package/core/dev/spikes/mods/kenaz-mod-probe/hooks/register.ts +0 -65
- package/core/dev/spikes/mods/kenaz-mod-probe/tsconfig.json +0 -3
|
@@ -1,516 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Kenaz Agent Connect — minimal example website (TASK_1940).
|
|
3
|
-
//
|
|
4
|
-
// This is the reference implementation SDK_GUIDE.md points readers at: one
|
|
5
|
-
// Node process, ZERO npm dependencies (node:http/node:crypto/node:fs only —
|
|
6
|
-
// deliberately not importing dashboard/scripts/agent-hub-fake-mcp.mjs even
|
|
7
|
-
// though that file has no external deps either, so this example stays
|
|
8
|
-
// copy-pasteable on its own, outside this repo, without dragging along the
|
|
9
|
-
// rest of KenazAI). It plays all three roles a real integration splits
|
|
10
|
-
// across a frontend + backend:
|
|
11
|
-
// 1. GET / — the page with the "連接 Kenaz" button (public/index.html)
|
|
12
|
-
// 2. POST /api/connect — mints a one-time token, returns a kenaz://connect
|
|
13
|
-
// deep link (PROTOCOL.md §1) — this is "the website's backend"
|
|
14
|
-
// 3. GET /api/status/:token — the frontend polls this to learn whether
|
|
15
|
-
// the agent has called kenaz_hello yet (there is no push channel —
|
|
16
|
-
// PROTOCOL.md §0: "Kenaz → Web:沒有回程通道")
|
|
17
|
-
// 4. POST /mcp — the website's own MCP endpoint (PROTOCOL.md §2):
|
|
18
|
-
// bearer-checks every request, exposes `kenaz_hello` (no-arg, records
|
|
19
|
-
// the call so /api/status can report it), `kenaz_wait_for_message`
|
|
20
|
-
// (TASK_1948, PROTOCOL.md §2 point 5 — long-polls a per-token mailbox
|
|
21
|
-
// so the Ansuz persona can keep listening for this site's next
|
|
22
|
-
// instruction after kenaz_hello), and one demo tool `echo`.
|
|
23
|
-
// 5. POST /message — delivers a message into a token's mailbox (not
|
|
24
|
-
// part of PROTOCOL.md itself — that only specifies the MCP tool's
|
|
25
|
-
// shape; this is this demo's stand-in for "however a real site's own
|
|
26
|
-
// chat UI / webhook hands the agent its next instruction").
|
|
27
|
-
//
|
|
28
|
-
// Run: node server.js (see README.md for the two follow-up steps)
|
|
29
|
-
|
|
30
|
-
import http from 'node:http';
|
|
31
|
-
import crypto from 'node:crypto';
|
|
32
|
-
import fs from 'node:fs';
|
|
33
|
-
import path from 'node:path';
|
|
34
|
-
import { fileURLToPath } from 'node:url';
|
|
35
|
-
|
|
36
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
37
|
-
|
|
38
|
-
// ── Token store ──────────────────────────────────────────────────────────
|
|
39
|
-
// One-time per "連接" click (PROTOCOL.md §1 `token`): minted fresh here,
|
|
40
|
-
// never reused across two different connect attempts. TTL-bound so a stale
|
|
41
|
-
// token from an abandoned attempt stops working on its own — this is the
|
|
42
|
-
// "撤銷建議" SDK_GUIDE.md's security section talks about; a real backend
|
|
43
|
-
// would also expose an explicit revoke path (DELETE /api/connect/:token or
|
|
44
|
-
// similar) and bind the token to the visitor's own login session, neither
|
|
45
|
-
// of which this demo has a session system to hang off.
|
|
46
|
-
const TOKEN_TTL_MS = 10 * 60 * 1000; // 10 minutes
|
|
47
|
-
|
|
48
|
-
// ── "Not installed" redirect config (TASK_1950, SDK_GUIDE.md §10) ───────
|
|
49
|
-
// No known app.kenazai.com install route exists yet — this is deliberately
|
|
50
|
-
// a placeholder, configurable via env var rather than a guessed URL (see
|
|
51
|
-
// SDK_GUIDE.md §10 "安裝頁 URL 從哪裡來"). A real site should point this at
|
|
52
|
-
// its own download page, or a page that reads the kenaz-release bucket's
|
|
53
|
-
// latest.json (see dashboard/scripts/publish-release.js) and redirects to
|
|
54
|
-
// the per-platform installer URL in it.
|
|
55
|
-
const DEFAULT_INSTALL_URL = process.env.KENAZ_INSTALL_URL || 'https://kenaz-install.example/placeholder';
|
|
56
|
-
// SDK_GUIDE.md §10 default: 8 seconds. Overridable so this demo (and anyone
|
|
57
|
-
// forking it) can tune the not-installed/still-approving tradeoff without
|
|
58
|
-
// editing public/index.html.
|
|
59
|
-
const DEFAULT_INSTALL_TIMEOUT_MS = Number(process.env.KENAZ_INSTALL_TIMEOUT_MS || 8000);
|
|
60
|
-
|
|
61
|
-
// Default kenaz_wait_for_message long-poll window (PROTOCOL.md §2 point 5's
|
|
62
|
-
// "建議在伺服器端阻塞 20-25 秒才回傳 message: null" — the low end of that
|
|
63
|
-
// range). Overridable via createServer({ waitTimeoutMs }) — the smoke test
|
|
64
|
-
// and the conformance suite pass small values so they don't have to sit
|
|
65
|
-
// through a real 20s wait.
|
|
66
|
-
const DEFAULT_WAIT_TIMEOUT_MS = 20 * 1000;
|
|
67
|
-
|
|
68
|
-
/** @type {Map<string, { createdAt: number, helloCalledAt: number|null }>} */
|
|
69
|
-
const tokens = new Map();
|
|
70
|
-
|
|
71
|
-
function mintToken() {
|
|
72
|
-
// base64url charset (A-Za-z0-9-_) is a strict subset of deep_link.rs's
|
|
73
|
-
// allowed token charset ([A-Za-z0-9._-]) — see PROTOCOL.md §1's token row.
|
|
74
|
-
const token = crypto.randomBytes(24).toString('base64url');
|
|
75
|
-
tokens.set(token, { createdAt: Date.now(), helloCalledAt: null });
|
|
76
|
-
return token;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function getValidToken(token) {
|
|
80
|
-
const entry = tokens.get(token);
|
|
81
|
-
if (!entry) return null;
|
|
82
|
-
if (Date.now() - entry.createdAt > TOKEN_TTL_MS) {
|
|
83
|
-
tokens.delete(token);
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
return entry;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Sweep expired tokens periodically so the demo doesn't leak memory across a
|
|
90
|
-
// long-running process. unref() so it never keeps the process alive on its
|
|
91
|
-
// own (matters for the smoke test's server.close()).
|
|
92
|
-
setInterval(() => {
|
|
93
|
-
const now = Date.now();
|
|
94
|
-
for (const [token, entry] of tokens) {
|
|
95
|
-
if (now - entry.createdAt > TOKEN_TTL_MS) tokens.delete(token);
|
|
96
|
-
}
|
|
97
|
-
}, 60 * 1000).unref();
|
|
98
|
-
|
|
99
|
-
// ── Mailbox: kenaz_wait_for_message (PROTOCOL.md §2 point 5, TASK_1948) ──
|
|
100
|
-
// One mailbox per token: a FIFO queue of undelivered messages, plus a list
|
|
101
|
-
// of long-poll waiters (agent calls currently blocked in kenaz_wait_for_
|
|
102
|
-
// message with nothing queued yet). POST /message either hands a fresh
|
|
103
|
-
// message straight to the oldest waiting long-poll call, or — if nobody is
|
|
104
|
-
// waiting right now — queues it for the next call. This is the website side
|
|
105
|
-
// of the "agent keeps listening" convention: a real site would deliver here
|
|
106
|
-
// from its own chat UI / webhook instead of a bare POST.
|
|
107
|
-
|
|
108
|
-
/** @type {Map<string, { queue: Array<{message: string, message_id: string}>, waiters: Array<(v: {message: string|null, message_id: string|null}) => void> }>} */
|
|
109
|
-
const mailboxes = new Map();
|
|
110
|
-
|
|
111
|
-
function getMailbox(token) {
|
|
112
|
-
let mb = mailboxes.get(token);
|
|
113
|
-
if (!mb) {
|
|
114
|
-
mb = { queue: [], waiters: [] };
|
|
115
|
-
mailboxes.set(token, mb);
|
|
116
|
-
}
|
|
117
|
-
return mb;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** Deliver a message into `token`'s mailbox. Returns the minted message_id. */
|
|
121
|
-
function deliverMessage(token, message) {
|
|
122
|
-
const mb = getMailbox(token);
|
|
123
|
-
const message_id = crypto.randomUUID();
|
|
124
|
-
const waiter = mb.waiters.shift();
|
|
125
|
-
if (waiter) {
|
|
126
|
-
waiter({ message, message_id });
|
|
127
|
-
} else {
|
|
128
|
-
mb.queue.push({ message, message_id });
|
|
129
|
-
}
|
|
130
|
-
return message_id;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* The kenaz_wait_for_message long-poll itself: resolves immediately if a
|
|
135
|
-
* message is already queued, otherwise blocks up to `timeoutMs` and
|
|
136
|
-
* resolves `{message: null, message_id: null}` if nothing arrives in time
|
|
137
|
-
* (PROTOCOL.md §2 point 5's "message 為 null" case — not an error).
|
|
138
|
-
* `timeoutMs` defaults to the spec's 20s floor; the smoke test and
|
|
139
|
-
* conformance suite override it to a small value so they don't have to
|
|
140
|
-
* actually sit through a real long-poll window.
|
|
141
|
-
*/
|
|
142
|
-
function waitForMessage(token, timeoutMs) {
|
|
143
|
-
const mb = getMailbox(token);
|
|
144
|
-
const queued = mb.queue.shift();
|
|
145
|
-
if (queued) return Promise.resolve(queued);
|
|
146
|
-
|
|
147
|
-
return new Promise((resolve) => {
|
|
148
|
-
let settled = false;
|
|
149
|
-
const resolveOnce = (value) => {
|
|
150
|
-
if (settled) return;
|
|
151
|
-
settled = true;
|
|
152
|
-
clearTimeout(timer);
|
|
153
|
-
resolve(value);
|
|
154
|
-
};
|
|
155
|
-
const timer = setTimeout(() => {
|
|
156
|
-
const idx = mb.waiters.indexOf(resolveOnce);
|
|
157
|
-
if (idx !== -1) mb.waiters.splice(idx, 1);
|
|
158
|
-
resolveOnce({ message: null, message_id: null });
|
|
159
|
-
}, timeoutMs);
|
|
160
|
-
timer.unref();
|
|
161
|
-
mb.waiters.push(resolveOnce);
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// ── kenaz://connect deep link builder (PROTOCOL.md §1) ──────────────────
|
|
166
|
-
|
|
167
|
-
function buildConnectUrl({ site, mcp, token, prompt, agent, v }) {
|
|
168
|
-
const params = new URLSearchParams();
|
|
169
|
-
params.set('site', site);
|
|
170
|
-
params.set('mcp', mcp);
|
|
171
|
-
params.set('token', token);
|
|
172
|
-
if (prompt) params.set('prompt', prompt);
|
|
173
|
-
if (agent) params.set('agent', agent);
|
|
174
|
-
if (v) params.set('v', v);
|
|
175
|
-
return `kenaz://connect?${params.toString()}`;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// ── MCP JSON-RPC (PROTOCOL.md §2 — the website's own MCP) ───────────────
|
|
179
|
-
// Same "Streamable HTTP" shape as dashboard/scripts/agent-hub-fake-mcp.mjs
|
|
180
|
-
// (single application/json body per POST, no SSE — this demo never streams
|
|
181
|
-
// anything) because that is the transport claude's `--mcp-config`
|
|
182
|
-
// `"type":"http"` / codex's `-c mcp_servers.*` overrides actually speak.
|
|
183
|
-
|
|
184
|
-
function jsonRpcResult(id, result) {
|
|
185
|
-
return { jsonrpc: '2.0', id, result };
|
|
186
|
-
}
|
|
187
|
-
function jsonRpcError(id, code, message) {
|
|
188
|
-
return { jsonrpc: '2.0', id: id ?? null, error: { code, message } };
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
async function handleMcpRpc(msg, { onKenazHello, token, waitTimeoutMs } = {}) {
|
|
192
|
-
if (!msg || msg.jsonrpc !== '2.0') {
|
|
193
|
-
return jsonRpcError(msg && msg.id, -32600, 'Invalid Request — expected jsonrpc:"2.0"');
|
|
194
|
-
}
|
|
195
|
-
switch (msg.method) {
|
|
196
|
-
case 'initialize':
|
|
197
|
-
return jsonRpcResult(msg.id, {
|
|
198
|
-
protocolVersion: '2025-06-18',
|
|
199
|
-
capabilities: { tools: {} },
|
|
200
|
-
serverInfo: { name: 'kenaz-connect-minimal-site', version: '1.0.0' },
|
|
201
|
-
});
|
|
202
|
-
case 'notifications/initialized':
|
|
203
|
-
return null; // notification — no response body
|
|
204
|
-
case 'tools/list':
|
|
205
|
-
return jsonRpcResult(msg.id, {
|
|
206
|
-
tools: [
|
|
207
|
-
{
|
|
208
|
-
name: 'kenaz_hello',
|
|
209
|
-
description: 'No-arg tool the Ansuz persona calls once at session start (PROTOCOL.md §2).',
|
|
210
|
-
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
211
|
-
// TASK_1949 (Agent Connect C-1b, PROTOCOL.md §2 point 6): a
|
|
212
|
-
// no-op notification, not destructive, and safe to call more
|
|
213
|
-
// than once — kenaz's claude branch pre-allows it via
|
|
214
|
-
// --allowedTools so the FIRST tool call of the session doesn't
|
|
215
|
-
// also stop for a terminal permission prompt.
|
|
216
|
-
annotations: { destructiveHint: false, idempotentHint: true },
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
name: 'kenaz_wait_for_message',
|
|
220
|
-
description:
|
|
221
|
-
'No-arg, optional (PROTOCOL.md §2 point 5). Long-polls this token\'s mailbox and ' +
|
|
222
|
-
'returns {message, message_id, end} — the Ansuz persona calls this repeatedly ' +
|
|
223
|
-
'after kenaz_hello to keep listening for the next instruction from this site.',
|
|
224
|
-
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
225
|
-
// Pure read of the mailbox — never mutates anything server-side.
|
|
226
|
-
annotations: { readOnlyHint: true },
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
name: 'echo',
|
|
230
|
-
description: 'Demo tool — echoes back whatever "text" argument it was given.',
|
|
231
|
-
inputSchema: {
|
|
232
|
-
type: 'object',
|
|
233
|
-
properties: { text: { type: 'string' } },
|
|
234
|
-
additionalProperties: false,
|
|
235
|
-
},
|
|
236
|
-
// Echoing back input has no side effect.
|
|
237
|
-
annotations: { readOnlyHint: true },
|
|
238
|
-
},
|
|
239
|
-
],
|
|
240
|
-
});
|
|
241
|
-
case 'tools/call': {
|
|
242
|
-
const toolName = msg.params && msg.params.name;
|
|
243
|
-
if (toolName === 'kenaz_hello') {
|
|
244
|
-
if (typeof onKenazHello === 'function') onKenazHello();
|
|
245
|
-
return jsonRpcResult(msg.id, {
|
|
246
|
-
content: [{ type: 'text', text: JSON.stringify({ ok: true }) }],
|
|
247
|
-
isError: false,
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
if (toolName === 'kenaz_wait_for_message') {
|
|
251
|
-
const { message, message_id } = await waitForMessage(token, waitTimeoutMs);
|
|
252
|
-
return jsonRpcResult(msg.id, {
|
|
253
|
-
content: [{ type: 'text', text: JSON.stringify({ message, message_id }) }],
|
|
254
|
-
isError: false,
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
if (toolName === 'echo') {
|
|
258
|
-
const text = (msg.params && msg.params.arguments && msg.params.arguments.text) || '';
|
|
259
|
-
return jsonRpcResult(msg.id, {
|
|
260
|
-
content: [{ type: 'text', text: JSON.stringify({ echo: text }) }],
|
|
261
|
-
isError: false,
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
return jsonRpcError(msg.id, -32602, `Unknown tool: ${JSON.stringify(toolName)}`);
|
|
265
|
-
}
|
|
266
|
-
default:
|
|
267
|
-
if (msg.id === undefined) return null;
|
|
268
|
-
return jsonRpcError(msg.id, -32601, `Method not found: ${msg.method}`);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
async function handleMcpRequest(req, res, body, { waitTimeoutMs = DEFAULT_WAIT_TIMEOUT_MS } = {}) {
|
|
273
|
-
const authHeader = req.headers['authorization'] || null;
|
|
274
|
-
const expected = authHeader && authHeader.startsWith('Bearer ') ? authHeader.slice(7) : null;
|
|
275
|
-
const entry = expected ? getValidToken(expected) : null;
|
|
276
|
-
|
|
277
|
-
if (!entry) {
|
|
278
|
-
// AC: "範例網站的 MCP 對錯誤 bearer 回 401(對照組)" — this is the
|
|
279
|
-
// ONLY auth check the whole example has; Kenaz itself never validates
|
|
280
|
-
// the token (PROTOCOL.md §2 point 1 — "Kenaz 不做任何驗證").
|
|
281
|
-
res.writeHead(401, { 'content-type': 'application/json' });
|
|
282
|
-
res.end(JSON.stringify({ error: 'unauthorized' }));
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
let parsed;
|
|
287
|
-
try {
|
|
288
|
-
parsed = JSON.parse(body || '{}');
|
|
289
|
-
} catch (e) {
|
|
290
|
-
res.writeHead(400, { 'content-type': 'application/json' });
|
|
291
|
-
res.end(JSON.stringify(jsonRpcError(null, -32700, `Parse error: ${e.message}`)));
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const onKenazHello = () => {
|
|
296
|
-
entry.helloCalledAt = Date.now();
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
const messages = Array.isArray(parsed) ? parsed : [parsed];
|
|
300
|
-
const responses = (
|
|
301
|
-
await Promise.all(messages.map((m) => handleMcpRpc(m, { onKenazHello, token: expected, waitTimeoutMs })))
|
|
302
|
-
).filter((r) => r !== null);
|
|
303
|
-
|
|
304
|
-
if (!req.headers['mcp-session-id']) {
|
|
305
|
-
res.setHeader('Mcp-Session-Id', crypto.randomUUID());
|
|
306
|
-
} else {
|
|
307
|
-
res.setHeader('Mcp-Session-Id', req.headers['mcp-session-id']);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
if (responses.length === 0) {
|
|
311
|
-
res.writeHead(202);
|
|
312
|
-
res.end();
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
res.writeHead(200, { 'content-type': 'application/json' });
|
|
317
|
-
res.end(JSON.stringify(Array.isArray(parsed) ? responses : responses[0]));
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// ── HTTP app ──────────────────────────────────────────────────────────────
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Inject the configured install-page URL + not-installed timeout into
|
|
324
|
-
* public/index.html's `data-*` attributes (TASK_1950). Plain string
|
|
325
|
-
* substitution — no templating engine needed for two placeholders, and
|
|
326
|
-
* pulling one in would be the wrong end of the YAGNI ladder for a
|
|
327
|
-
* zero-dependency demo (see server.js's file-header comment).
|
|
328
|
-
*/
|
|
329
|
-
function renderIndexHtml({ installUrl, installTimeoutMs }) {
|
|
330
|
-
const html = fs.readFileSync(path.join(__dirname, 'public', 'index.html'), 'utf8');
|
|
331
|
-
return html
|
|
332
|
-
.replace('__KENAZ_INSTALL_URL__', installUrl)
|
|
333
|
-
.replace('__KENAZ_INSTALL_TIMEOUT_MS__', String(installTimeoutMs));
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
function readBody(req) {
|
|
337
|
-
return new Promise((resolve, reject) => {
|
|
338
|
-
const chunks = [];
|
|
339
|
-
req.on('data', (c) => chunks.push(c));
|
|
340
|
-
req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
341
|
-
req.on('error', reject);
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Build the HTTP request handler. `baseUrl` (e.g. "http://127.0.0.1:8420")
|
|
347
|
-
* is injected rather than read from `req` so the deep link's `site=`/`mcp=`
|
|
348
|
-
* always match whatever origin the browser actually loaded the page from —
|
|
349
|
-
* see createServer() below.
|
|
350
|
-
*/
|
|
351
|
-
export function createRequestListener(
|
|
352
|
-
getBaseUrl,
|
|
353
|
-
{
|
|
354
|
-
waitTimeoutMs = DEFAULT_WAIT_TIMEOUT_MS,
|
|
355
|
-
installUrl = DEFAULT_INSTALL_URL,
|
|
356
|
-
installTimeoutMs = DEFAULT_INSTALL_TIMEOUT_MS,
|
|
357
|
-
} = {},
|
|
358
|
-
) {
|
|
359
|
-
return async (req, res) => {
|
|
360
|
-
const url = new URL(req.url, 'http://internal');
|
|
361
|
-
|
|
362
|
-
if (req.method === 'GET' && url.pathname === '/install-redirect.js') {
|
|
363
|
-
// Served as a real static file (not inlined into index.html) so the
|
|
364
|
-
// exact same module test/smoke.test.mjs imports is what the browser
|
|
365
|
-
// runs — see install-redirect.js's file-header comment.
|
|
366
|
-
const js = fs.readFileSync(path.join(__dirname, 'public', 'install-redirect.js'), 'utf8');
|
|
367
|
-
res.writeHead(200, { 'content-type': 'text/javascript; charset=utf-8' });
|
|
368
|
-
res.end(js);
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
if (req.method === 'POST' && url.pathname === '/message') {
|
|
373
|
-
// Deliver a message into a token's mailbox (TASK_1948) — stands in for
|
|
374
|
-
// whatever real trigger a production site would use (its own chat UI,
|
|
375
|
-
// a webhook, a queue consumer...) to hand the agent its next
|
|
376
|
-
// instruction via kenaz_wait_for_message. Not part of PROTOCOL.md
|
|
377
|
-
// itself — that only specifies the MCP tool's shape, not how a
|
|
378
|
-
// website gets a message INTO its own backend in the first place.
|
|
379
|
-
const body = await readBody(req);
|
|
380
|
-
let payload;
|
|
381
|
-
try {
|
|
382
|
-
payload = JSON.parse(body || '{}');
|
|
383
|
-
} catch (e) {
|
|
384
|
-
res.writeHead(400, { 'content-type': 'application/json' });
|
|
385
|
-
res.end(JSON.stringify({ error: `invalid JSON body: ${e.message}` }));
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
const { token, message } = payload;
|
|
389
|
-
const entry = typeof token === 'string' ? getValidToken(token) : null;
|
|
390
|
-
if (!entry) {
|
|
391
|
-
res.writeHead(404, { 'content-type': 'application/json' });
|
|
392
|
-
res.end(JSON.stringify({ error: 'unknown or expired token' }));
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
if (typeof message !== 'string' || message.length === 0) {
|
|
396
|
-
res.writeHead(400, { 'content-type': 'application/json' });
|
|
397
|
-
res.end(JSON.stringify({ error: 'message must be a non-empty string' }));
|
|
398
|
-
return;
|
|
399
|
-
}
|
|
400
|
-
const message_id = deliverMessage(token, message);
|
|
401
|
-
res.writeHead(200, { 'content-type': 'application/json' });
|
|
402
|
-
res.end(JSON.stringify({ ok: true, message_id }));
|
|
403
|
-
return;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
if (req.method === 'GET' && url.pathname === '/') {
|
|
407
|
-
const html = renderIndexHtml({ installUrl, installTimeoutMs });
|
|
408
|
-
res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
|
|
409
|
-
res.end(html);
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
if (req.method === 'POST' && url.pathname === '/api/connect') {
|
|
414
|
-
const body = await readBody(req);
|
|
415
|
-
let prompt = '';
|
|
416
|
-
try {
|
|
417
|
-
prompt = JSON.parse(body || '{}').prompt || '';
|
|
418
|
-
} catch {
|
|
419
|
-
// ignore — empty prompt is a valid, documented case (PROTOCOL.md §1)
|
|
420
|
-
}
|
|
421
|
-
const token = mintToken();
|
|
422
|
-
const base = getBaseUrl();
|
|
423
|
-
const deepLink = buildConnectUrl({
|
|
424
|
-
site: base,
|
|
425
|
-
mcp: `${base}/mcp`,
|
|
426
|
-
token,
|
|
427
|
-
prompt,
|
|
428
|
-
});
|
|
429
|
-
res.writeHead(200, { 'content-type': 'application/json' });
|
|
430
|
-
res.end(JSON.stringify({ deepLink, token }));
|
|
431
|
-
return;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
if (req.method === 'GET' && url.pathname.startsWith('/api/status/')) {
|
|
435
|
-
const token = url.pathname.slice('/api/status/'.length);
|
|
436
|
-
const entry = getValidToken(token);
|
|
437
|
-
res.writeHead(200, { 'content-type': 'application/json' });
|
|
438
|
-
res.end(
|
|
439
|
-
JSON.stringify({
|
|
440
|
-
known: !!entry,
|
|
441
|
-
connected: !!(entry && entry.helloCalledAt),
|
|
442
|
-
calledAt: entry ? entry.helloCalledAt : null,
|
|
443
|
-
}),
|
|
444
|
-
);
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
if (url.pathname === '/mcp') {
|
|
449
|
-
if (req.method === 'GET') {
|
|
450
|
-
res.writeHead(200, { 'content-type': 'text/plain' });
|
|
451
|
-
res.end('kenaz-connect-minimal-site MCP: POST JSON-RPC here\n');
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
if (req.method === 'POST') {
|
|
455
|
-
const body = await readBody(req);
|
|
456
|
-
await handleMcpRequest(req, res, body, { waitTimeoutMs });
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
res.writeHead(405, { 'content-type': 'application/json' });
|
|
460
|
-
res.end(JSON.stringify({ error: 'method not allowed' }));
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
res.writeHead(404, { 'content-type': 'application/json' });
|
|
465
|
-
res.end(JSON.stringify({ error: 'not found' }));
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
/**
|
|
470
|
-
* Start the demo server on `port` (0 = OS-assigned, used by the smoke test).
|
|
471
|
-
* Returns { server, port, close }.
|
|
472
|
-
*/
|
|
473
|
-
export function createServer({
|
|
474
|
-
port = 0,
|
|
475
|
-
host = '127.0.0.1',
|
|
476
|
-
waitTimeoutMs = DEFAULT_WAIT_TIMEOUT_MS,
|
|
477
|
-
installUrl = DEFAULT_INSTALL_URL,
|
|
478
|
-
installTimeoutMs = DEFAULT_INSTALL_TIMEOUT_MS,
|
|
479
|
-
} = {}) {
|
|
480
|
-
let baseUrl = `http://${host}:${port}`;
|
|
481
|
-
const server = http.createServer(
|
|
482
|
-
createRequestListener(() => baseUrl, { waitTimeoutMs, installUrl, installTimeoutMs }),
|
|
483
|
-
);
|
|
484
|
-
return {
|
|
485
|
-
server,
|
|
486
|
-
async listen() {
|
|
487
|
-
await new Promise((resolve) => server.listen(port, host, resolve));
|
|
488
|
-
const actualPort = server.address().port;
|
|
489
|
-
baseUrl = `http://${host}:${actualPort}`;
|
|
490
|
-
return actualPort;
|
|
491
|
-
},
|
|
492
|
-
get baseUrl() {
|
|
493
|
-
return baseUrl;
|
|
494
|
-
},
|
|
495
|
-
close() {
|
|
496
|
-
return new Promise((resolve) => server.close(() => resolve()));
|
|
497
|
-
},
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
async function runCli() {
|
|
502
|
-
const requestedPort = Number(process.env.PORT || 8420);
|
|
503
|
-
const demo = createServer({ port: requestedPort });
|
|
504
|
-
const actualPort = await demo.listen();
|
|
505
|
-
console.log(`[minimal-site] listening on ${demo.baseUrl}`);
|
|
506
|
-
console.log(`[minimal-site] open ${demo.baseUrl} in a browser to try "連接 Kenaz"`);
|
|
507
|
-
console.log('[minimal-site] MCP endpoint (bearer-protected): ' + demo.baseUrl + '/mcp');
|
|
508
|
-
if (actualPort !== requestedPort) {
|
|
509
|
-
console.log(`[minimal-site] note: requested port ${requestedPort} was busy, using ${actualPort} instead`);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
const isMain = process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
514
|
-
if (isMain) {
|
|
515
|
-
runCli();
|
|
516
|
-
}
|