@syrin/cli 1.3.0
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/LICENSE +15 -0
- package/README.md +302 -0
- package/dist/cli/commands/analyse.d.ts +16 -0
- package/dist/cli/commands/analyse.js +61 -0
- package/dist/cli/commands/dev.d.ts +23 -0
- package/dist/cli/commands/dev.js +419 -0
- package/dist/cli/commands/doctor.d.ts +10 -0
- package/dist/cli/commands/doctor.js +195 -0
- package/dist/cli/commands/index.d.ts +12 -0
- package/dist/cli/commands/index.js +12 -0
- package/dist/cli/commands/init.d.ts +16 -0
- package/dist/cli/commands/init.js +90 -0
- package/dist/cli/commands/list.d.ts +15 -0
- package/dist/cli/commands/list.js +50 -0
- package/dist/cli/commands/rollback.d.ts +12 -0
- package/dist/cli/commands/rollback.js +101 -0
- package/dist/cli/commands/test.d.ts +31 -0
- package/dist/cli/commands/test.js +88 -0
- package/dist/cli/commands/update.d.ts +9 -0
- package/dist/cli/commands/update.js +76 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.js +342 -0
- package/dist/cli/prompts/index.d.ts +5 -0
- package/dist/cli/prompts/index.js +5 -0
- package/dist/cli/prompts/init-prompt.d.ts +17 -0
- package/dist/cli/prompts/init-prompt.js +263 -0
- package/dist/cli/utils/command-error-handler.d.ts +14 -0
- package/dist/cli/utils/command-error-handler.js +35 -0
- package/dist/cli/utils/common-types.d.ts +24 -0
- package/dist/cli/utils/common-types.js +6 -0
- package/dist/cli/utils/connection-handler.d.ts +37 -0
- package/dist/cli/utils/connection-handler.js +90 -0
- package/dist/cli/utils/index.d.ts +11 -0
- package/dist/cli/utils/index.js +11 -0
- package/dist/cli/utils/option-parsers.d.ts +41 -0
- package/dist/cli/utils/option-parsers.js +92 -0
- package/dist/cli/utils/output-utils.d.ts +12 -0
- package/dist/cli/utils/output-utils.js +21 -0
- package/dist/cli/utils/transport-resolver.d.ts +33 -0
- package/dist/cli/utils/transport-resolver.js +82 -0
- package/dist/cli/utils/version-banner.d.ts +10 -0
- package/dist/cli/utils/version-banner.js +26 -0
- package/dist/config/env-checker.d.ts +37 -0
- package/dist/config/env-checker.js +136 -0
- package/dist/config/generator.d.ts +19 -0
- package/dist/config/generator.js +196 -0
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.js +9 -0
- package/dist/config/loader.d.ts +19 -0
- package/dist/config/loader.js +57 -0
- package/dist/config/schema.d.ts +42 -0
- package/dist/config/schema.js +181 -0
- package/dist/config/syrin.template.yaml +127 -0
- package/dist/config/types.d.ts +87 -0
- package/dist/config/types.js +6 -0
- package/dist/constants/app.d.ts +9 -0
- package/dist/constants/app.js +9 -0
- package/dist/constants/commands.d.ts +43 -0
- package/dist/constants/commands.js +43 -0
- package/dist/constants/defaults.d.ts +18 -0
- package/dist/constants/defaults.js +18 -0
- package/dist/constants/env-vars.d.ts +11 -0
- package/dist/constants/env-vars.js +11 -0
- package/dist/constants/icons.d.ts +23 -0
- package/dist/constants/icons.js +23 -0
- package/dist/constants/index.d.ts +17 -0
- package/dist/constants/index.js +17 -0
- package/dist/constants/labels.d.ts +38 -0
- package/dist/constants/labels.js +42 -0
- package/dist/constants/links.d.ts +10 -0
- package/dist/constants/links.js +11 -0
- package/dist/constants/list.d.ts +10 -0
- package/dist/constants/list.js +9 -0
- package/dist/constants/llm.d.ts +26 -0
- package/dist/constants/llm.js +25 -0
- package/dist/constants/messages.d.ts +107 -0
- package/dist/constants/messages.js +138 -0
- package/dist/constants/paths.d.ts +29 -0
- package/dist/constants/paths.js +29 -0
- package/dist/constants/transport.d.ts +9 -0
- package/dist/constants/transport.js +8 -0
- package/dist/events/emitter.d.ts +64 -0
- package/dist/events/emitter.js +142 -0
- package/dist/events/event-type.d.ts +66 -0
- package/dist/events/event-type.js +81 -0
- package/dist/events/payloads/diagnostics.d.ts +24 -0
- package/dist/events/payloads/diagnostics.js +5 -0
- package/dist/events/payloads/index.d.ts +15 -0
- package/dist/events/payloads/index.js +6 -0
- package/dist/events/payloads/llm.d.ts +58 -0
- package/dist/events/payloads/llm.js +6 -0
- package/dist/events/payloads/registry.d.ts +28 -0
- package/dist/events/payloads/registry.js +5 -0
- package/dist/events/payloads/session.d.ts +32 -0
- package/dist/events/payloads/session.js +5 -0
- package/dist/events/payloads/testing.d.ts +17 -0
- package/dist/events/payloads/testing.js +5 -0
- package/dist/events/payloads/tool.d.ts +29 -0
- package/dist/events/payloads/tool.js +5 -0
- package/dist/events/payloads/transport.d.ts +30 -0
- package/dist/events/payloads/transport.js +5 -0
- package/dist/events/payloads/validation.d.ts +37 -0
- package/dist/events/payloads/validation.js +5 -0
- package/dist/events/payloads/workflow.d.ts +45 -0
- package/dist/events/payloads/workflow.js +5 -0
- package/dist/events/store/file-store.d.ts +37 -0
- package/dist/events/store/file-store.js +113 -0
- package/dist/events/store/index.d.ts +7 -0
- package/dist/events/store/index.js +6 -0
- package/dist/events/store/memory-store.d.ts +26 -0
- package/dist/events/store/memory-store.js +39 -0
- package/dist/events/store.d.ts +11 -0
- package/dist/events/store.js +2 -0
- package/dist/events/types.d.ts +14 -0
- package/dist/events/types.js +2 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +30 -0
- package/dist/presentation/analysis-ui.d.ts +24 -0
- package/dist/presentation/analysis-ui.js +158 -0
- package/dist/presentation/dev/chat-ui-types.d.ts +68 -0
- package/dist/presentation/dev/chat-ui-types.js +5 -0
- package/dist/presentation/dev/chat-ui.d.ts +61 -0
- package/dist/presentation/dev/chat-ui.js +714 -0
- package/dist/presentation/dev/components/assistant-message.d.ts +19 -0
- package/dist/presentation/dev/components/assistant-message.js +36 -0
- package/dist/presentation/dev/components/header.d.ts +16 -0
- package/dist/presentation/dev/components/header.js +22 -0
- package/dist/presentation/dev/components/index.d.ts +13 -0
- package/dist/presentation/dev/components/index.js +13 -0
- package/dist/presentation/dev/components/input-panel.d.ts +22 -0
- package/dist/presentation/dev/components/input-panel.js +43 -0
- package/dist/presentation/dev/components/message-component.d.ts +16 -0
- package/dist/presentation/dev/components/message-component.js +51 -0
- package/dist/presentation/dev/components/messages-list.d.ts +24 -0
- package/dist/presentation/dev/components/messages-list.js +48 -0
- package/dist/presentation/dev/components/system-message.d.ts +16 -0
- package/dist/presentation/dev/components/system-message.js +26 -0
- package/dist/presentation/dev/components/user-message.d.ts +21 -0
- package/dist/presentation/dev/components/user-message.js +35 -0
- package/dist/presentation/dev/components/welcome-banner.d.ts +24 -0
- package/dist/presentation/dev/components/welcome-banner.js +146 -0
- package/dist/presentation/dev/goodbye-messages.d.ts +31 -0
- package/dist/presentation/dev/goodbye-messages.js +100 -0
- package/dist/presentation/dev/index.d.ts +5 -0
- package/dist/presentation/dev/index.js +5 -0
- package/dist/presentation/dev/text-wrapper.d.ts +30 -0
- package/dist/presentation/dev/text-wrapper.js +74 -0
- package/dist/presentation/dev-ui.d.ts +33 -0
- package/dist/presentation/dev-ui.js +246 -0
- package/dist/presentation/doctor-ui.d.ts +40 -0
- package/dist/presentation/doctor-ui.js +157 -0
- package/dist/presentation/init-ui.d.ts +14 -0
- package/dist/presentation/init-ui.js +41 -0
- package/dist/presentation/list-ui.d.ts +44 -0
- package/dist/presentation/list-ui.js +139 -0
- package/dist/presentation/test-ui.d.ts +49 -0
- package/dist/presentation/test-ui.js +358 -0
- package/dist/runtime/analysis/analyser.d.ts +14 -0
- package/dist/runtime/analysis/analyser.js +88 -0
- package/dist/runtime/analysis/dependencies.d.ts +10 -0
- package/dist/runtime/analysis/dependencies.js +140 -0
- package/dist/runtime/analysis/index.d.ts +10 -0
- package/dist/runtime/analysis/index.js +10 -0
- package/dist/runtime/analysis/indexer.d.ts +10 -0
- package/dist/runtime/analysis/indexer.js +62 -0
- package/dist/runtime/analysis/loader.d.ts +15 -0
- package/dist/runtime/analysis/loader.js +47 -0
- package/dist/runtime/analysis/normalizer.d.ts +14 -0
- package/dist/runtime/analysis/normalizer.js +184 -0
- package/dist/runtime/analysis/rules/__test-helpers__.d.ts +18 -0
- package/dist/runtime/analysis/rules/__test-helpers__.js +40 -0
- package/dist/runtime/analysis/rules/base.d.ts +38 -0
- package/dist/runtime/analysis/rules/base.js +23 -0
- package/dist/runtime/analysis/rules/error-codes.d.ts +64 -0
- package/dist/runtime/analysis/rules/error-codes.js +73 -0
- package/dist/runtime/analysis/rules/errors/e000-tool-not-found.d.ts +35 -0
- package/dist/runtime/analysis/rules/errors/e000-tool-not-found.js +32 -0
- package/dist/runtime/analysis/rules/errors/e001-missing-output-schema.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e001-missing-output-schema.js +30 -0
- package/dist/runtime/analysis/rules/errors/e002-underspecified-input.d.ts +24 -0
- package/dist/runtime/analysis/rules/errors/e002-underspecified-input.js +52 -0
- package/dist/runtime/analysis/rules/errors/e003-type-mismatch.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e003-type-mismatch.js +73 -0
- package/dist/runtime/analysis/rules/errors/e004-free-text-propagation.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e004-free-text-propagation.js +47 -0
- package/dist/runtime/analysis/rules/errors/e005-tool-ambiguity.d.ts +25 -0
- package/dist/runtime/analysis/rules/errors/e005-tool-ambiguity.js +73 -0
- package/dist/runtime/analysis/rules/errors/e006-param-not-in-description.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e006-param-not-in-description.js +57 -0
- package/dist/runtime/analysis/rules/errors/e007-output-not-guaranteed.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e007-output-not-guaranteed.js +56 -0
- package/dist/runtime/analysis/rules/errors/e008-circular-dependency.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e008-circular-dependency.js +84 -0
- package/dist/runtime/analysis/rules/errors/e009-implicit-user-input.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e009-implicit-user-input.js +89 -0
- package/dist/runtime/analysis/rules/errors/e010-non-serializable.d.ts +25 -0
- package/dist/runtime/analysis/rules/errors/e010-non-serializable.js +46 -0
- package/dist/runtime/analysis/rules/errors/e011-missing-tool-description.d.ts +24 -0
- package/dist/runtime/analysis/rules/errors/e011-missing-tool-description.js +33 -0
- package/dist/runtime/analysis/rules/errors/e012-side-effect-detected.d.ts +39 -0
- package/dist/runtime/analysis/rules/errors/e012-side-effect-detected.js +40 -0
- package/dist/runtime/analysis/rules/errors/e013-non-deterministic-output.d.ts +37 -0
- package/dist/runtime/analysis/rules/errors/e013-non-deterministic-output.js +34 -0
- package/dist/runtime/analysis/rules/errors/e013-output-explosion.d.ts +39 -0
- package/dist/runtime/analysis/rules/errors/e013-output-explosion.js +36 -0
- package/dist/runtime/analysis/rules/errors/e014-hidden-dependency.d.ts +42 -0
- package/dist/runtime/analysis/rules/errors/e014-hidden-dependency.js +46 -0
- package/dist/runtime/analysis/rules/errors/e014-output-explosion.d.ts +39 -0
- package/dist/runtime/analysis/rules/errors/e014-output-explosion.js +36 -0
- package/dist/runtime/analysis/rules/errors/e015-hidden-dependency.d.ts +42 -0
- package/dist/runtime/analysis/rules/errors/e015-hidden-dependency.js +46 -0
- package/dist/runtime/analysis/rules/errors/e015-unbounded-execution.d.ts +44 -0
- package/dist/runtime/analysis/rules/errors/e015-unbounded-execution.js +66 -0
- package/dist/runtime/analysis/rules/errors/e016-output-validation-failed.d.ts +43 -0
- package/dist/runtime/analysis/rules/errors/e016-output-validation-failed.js +42 -0
- package/dist/runtime/analysis/rules/errors/e016-unbounded-execution.d.ts +44 -0
- package/dist/runtime/analysis/rules/errors/e016-unbounded-execution.js +66 -0
- package/dist/runtime/analysis/rules/errors/e017-input-validation-failed.d.ts +57 -0
- package/dist/runtime/analysis/rules/errors/e017-input-validation-failed.js +80 -0
- package/dist/runtime/analysis/rules/errors/e017-output-validation-failed.d.ts +43 -0
- package/dist/runtime/analysis/rules/errors/e017-output-validation-failed.js +42 -0
- package/dist/runtime/analysis/rules/errors/e018-input-validation-failed.d.ts +57 -0
- package/dist/runtime/analysis/rules/errors/e018-input-validation-failed.js +80 -0
- package/dist/runtime/analysis/rules/errors/e018-tool-execution-failed.d.ts +38 -0
- package/dist/runtime/analysis/rules/errors/e018-tool-execution-failed.js +37 -0
- package/dist/runtime/analysis/rules/errors/e019-tool-execution-failed.d.ts +38 -0
- package/dist/runtime/analysis/rules/errors/e019-tool-execution-failed.js +37 -0
- package/dist/runtime/analysis/rules/errors/e019-unexpected-test-result.d.ts +65 -0
- package/dist/runtime/analysis/rules/errors/e019-unexpected-test-result.js +109 -0
- package/dist/runtime/analysis/rules/errors/e020-unexpected-test-result.d.ts +65 -0
- package/dist/runtime/analysis/rules/errors/e020-unexpected-test-result.js +109 -0
- package/dist/runtime/analysis/rules/errors/e100-missing-output-schema.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e100-missing-output-schema.js +30 -0
- package/dist/runtime/analysis/rules/errors/e101-missing-tool-description.d.ts +24 -0
- package/dist/runtime/analysis/rules/errors/e101-missing-tool-description.js +33 -0
- package/dist/runtime/analysis/rules/errors/e102-underspecified-input.d.ts +24 -0
- package/dist/runtime/analysis/rules/errors/e102-underspecified-input.js +52 -0
- package/dist/runtime/analysis/rules/errors/e103-type-mismatch.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e103-type-mismatch.js +72 -0
- package/dist/runtime/analysis/rules/errors/e104-param-not-in-description.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e104-param-not-in-description.js +57 -0
- package/dist/runtime/analysis/rules/errors/e105-free-text-propagation.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e105-free-text-propagation.js +47 -0
- package/dist/runtime/analysis/rules/errors/e106-output-not-guaranteed.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e106-output-not-guaranteed.js +58 -0
- package/dist/runtime/analysis/rules/errors/e107-circular-dependency.d.ts +22 -0
- package/dist/runtime/analysis/rules/errors/e107-circular-dependency.js +84 -0
- package/dist/runtime/analysis/rules/errors/e108-implicit-user-input.d.ts +23 -0
- package/dist/runtime/analysis/rules/errors/e108-implicit-user-input.js +94 -0
- package/dist/runtime/analysis/rules/errors/e109-non-serializable.d.ts +25 -0
- package/dist/runtime/analysis/rules/errors/e109-non-serializable.js +44 -0
- package/dist/runtime/analysis/rules/errors/e110-tool-ambiguity.d.ts +25 -0
- package/dist/runtime/analysis/rules/errors/e110-tool-ambiguity.js +73 -0
- package/dist/runtime/analysis/rules/errors/e200-input-validation-failed.d.ts +57 -0
- package/dist/runtime/analysis/rules/errors/e200-input-validation-failed.js +71 -0
- package/dist/runtime/analysis/rules/errors/e300-output-validation-failed.d.ts +43 -0
- package/dist/runtime/analysis/rules/errors/e300-output-validation-failed.js +44 -0
- package/dist/runtime/analysis/rules/errors/e301-output-explosion.d.ts +39 -0
- package/dist/runtime/analysis/rules/errors/e301-output-explosion.js +36 -0
- package/dist/runtime/analysis/rules/errors/e400-tool-execution-failed.d.ts +38 -0
- package/dist/runtime/analysis/rules/errors/e400-tool-execution-failed.js +37 -0
- package/dist/runtime/analysis/rules/errors/e403-unbounded-execution.d.ts +44 -0
- package/dist/runtime/analysis/rules/errors/e403-unbounded-execution.js +66 -0
- package/dist/runtime/analysis/rules/errors/e500-side-effect-detected.d.ts +39 -0
- package/dist/runtime/analysis/rules/errors/e500-side-effect-detected.js +40 -0
- package/dist/runtime/analysis/rules/errors/e501-hidden-dependency.d.ts +47 -0
- package/dist/runtime/analysis/rules/errors/e501-hidden-dependency.js +46 -0
- package/dist/runtime/analysis/rules/errors/e600-unexpected-test-result.d.ts +65 -0
- package/dist/runtime/analysis/rules/errors/e600-unexpected-test-result.js +109 -0
- package/dist/runtime/analysis/rules/index.d.ts +18 -0
- package/dist/runtime/analysis/rules/index.js +94 -0
- package/dist/runtime/analysis/rules/warnings/w001-implicit-dependency.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w001-implicit-dependency.js +39 -0
- package/dist/runtime/analysis/rules/warnings/w002-free-text-without-normalization.d.ts +24 -0
- package/dist/runtime/analysis/rules/warnings/w002-free-text-without-normalization.js +40 -0
- package/dist/runtime/analysis/rules/warnings/w003-missing-examples.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w003-missing-examples.js +84 -0
- package/dist/runtime/analysis/rules/warnings/w004-overloaded-responsibility.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w004-overloaded-responsibility.js +96 -0
- package/dist/runtime/analysis/rules/warnings/w005-generic-description.d.ts +53 -0
- package/dist/runtime/analysis/rules/warnings/w005-generic-description.js +108 -0
- package/dist/runtime/analysis/rules/warnings/w006-optional-as-required.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w006-optional-as-required.js +44 -0
- package/dist/runtime/analysis/rules/warnings/w007-broad-output-schema.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w007-broad-output-schema.js +37 -0
- package/dist/runtime/analysis/rules/warnings/w008-multiple-entry-points.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w008-multiple-entry-points.js +97 -0
- package/dist/runtime/analysis/rules/warnings/w009-hidden-side-effects.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w009-hidden-side-effects.js +88 -0
- package/dist/runtime/analysis/rules/warnings/w010-output-not-reusable.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w010-output-not-reusable.js +81 -0
- package/dist/runtime/analysis/rules/warnings/w021-weak-schema.d.ts +40 -0
- package/dist/runtime/analysis/rules/warnings/w021-weak-schema.js +32 -0
- package/dist/runtime/analysis/rules/warnings/w022-high-entropy-output.d.ts +39 -0
- package/dist/runtime/analysis/rules/warnings/w022-high-entropy-output.js +36 -0
- package/dist/runtime/analysis/rules/warnings/w023-unstable-defaults.d.ts +38 -0
- package/dist/runtime/analysis/rules/warnings/w023-unstable-defaults.js +36 -0
- package/dist/runtime/analysis/rules/warnings/w100-implicit-dependency.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w100-implicit-dependency.js +89 -0
- package/dist/runtime/analysis/rules/warnings/w101-free-text-without-normalization.d.ts +24 -0
- package/dist/runtime/analysis/rules/warnings/w101-free-text-without-normalization.js +40 -0
- package/dist/runtime/analysis/rules/warnings/w102-missing-examples.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w102-missing-examples.js +76 -0
- package/dist/runtime/analysis/rules/warnings/w103-overloaded-responsibility.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w103-overloaded-responsibility.js +91 -0
- package/dist/runtime/analysis/rules/warnings/w104-generic-description.d.ts +53 -0
- package/dist/runtime/analysis/rules/warnings/w104-generic-description.js +108 -0
- package/dist/runtime/analysis/rules/warnings/w105-optional-as-required.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w105-optional-as-required.js +45 -0
- package/dist/runtime/analysis/rules/warnings/w106-broad-output-schema.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w106-broad-output-schema.js +37 -0
- package/dist/runtime/analysis/rules/warnings/w107-multiple-entry-points.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w107-multiple-entry-points.js +97 -0
- package/dist/runtime/analysis/rules/warnings/w108-hidden-side-effects.d.ts +23 -0
- package/dist/runtime/analysis/rules/warnings/w108-hidden-side-effects.js +94 -0
- package/dist/runtime/analysis/rules/warnings/w109-output-not-reusable.d.ts +22 -0
- package/dist/runtime/analysis/rules/warnings/w109-output-not-reusable.js +63 -0
- package/dist/runtime/analysis/rules/warnings/w110-weak-schema.d.ts +40 -0
- package/dist/runtime/analysis/rules/warnings/w110-weak-schema.js +32 -0
- package/dist/runtime/analysis/rules/warnings/w300-high-entropy-output.d.ts +39 -0
- package/dist/runtime/analysis/rules/warnings/w300-high-entropy-output.js +47 -0
- package/dist/runtime/analysis/rules/warnings/w301-unstable-defaults.d.ts +38 -0
- package/dist/runtime/analysis/rules/warnings/w301-unstable-defaults.js +36 -0
- package/dist/runtime/analysis/strict-mode.d.ts +21 -0
- package/dist/runtime/analysis/strict-mode.js +44 -0
- package/dist/runtime/analysis/types.d.ts +133 -0
- package/dist/runtime/analysis/types.js +6 -0
- package/dist/runtime/analysis/utils.d.ts +19 -0
- package/dist/runtime/analysis/utils.js +21 -0
- package/dist/runtime/dev/data-manager.d.ts +55 -0
- package/dist/runtime/dev/data-manager.js +87 -0
- package/dist/runtime/dev/event-mapper.d.ts +100 -0
- package/dist/runtime/dev/event-mapper.js +400 -0
- package/dist/runtime/dev/formatter.d.ts +94 -0
- package/dist/runtime/dev/formatter.js +236 -0
- package/dist/runtime/dev/index.d.ts +9 -0
- package/dist/runtime/dev/index.js +9 -0
- package/dist/runtime/dev/repl.d.ts +114 -0
- package/dist/runtime/dev/repl.js +310 -0
- package/dist/runtime/dev/session.d.ts +86 -0
- package/dist/runtime/dev/session.js +447 -0
- package/dist/runtime/dev/stack-trace.d.ts +77 -0
- package/dist/runtime/dev/stack-trace.js +286 -0
- package/dist/runtime/dev/types.d.ts +54 -0
- package/dist/runtime/dev/types.js +5 -0
- package/dist/runtime/llm/claude.d.ts +27 -0
- package/dist/runtime/llm/claude.js +150 -0
- package/dist/runtime/llm/factory.d.ts +30 -0
- package/dist/runtime/llm/factory.js +78 -0
- package/dist/runtime/llm/index.d.ts +10 -0
- package/dist/runtime/llm/index.js +10 -0
- package/dist/runtime/llm/ollama.d.ts +45 -0
- package/dist/runtime/llm/ollama.js +449 -0
- package/dist/runtime/llm/openai.d.ts +27 -0
- package/dist/runtime/llm/openai.js +170 -0
- package/dist/runtime/llm/provider.d.ts +32 -0
- package/dist/runtime/llm/provider.js +6 -0
- package/dist/runtime/llm/types.d.ts +55 -0
- package/dist/runtime/llm/types.js +6 -0
- package/dist/runtime/mcp/client/base.d.ts +40 -0
- package/dist/runtime/mcp/client/base.js +157 -0
- package/dist/runtime/mcp/client/manager.d.ts +91 -0
- package/dist/runtime/mcp/client/manager.js +248 -0
- package/dist/runtime/mcp/client/process.d.ts +31 -0
- package/dist/runtime/mcp/client/process.js +82 -0
- package/dist/runtime/mcp/connection.d.ts +63 -0
- package/dist/runtime/mcp/connection.js +449 -0
- package/dist/runtime/mcp/index.d.ts +9 -0
- package/dist/runtime/mcp/index.js +9 -0
- package/dist/runtime/mcp/list.d.ts +50 -0
- package/dist/runtime/mcp/list.js +65 -0
- package/dist/runtime/mcp/stdio-transport.d.ts +23 -0
- package/dist/runtime/mcp/stdio-transport.js +71 -0
- package/dist/runtime/mcp/types.d.ts +85 -0
- package/dist/runtime/mcp/types.js +6 -0
- package/dist/runtime/sandbox/executor.d.ts +102 -0
- package/dist/runtime/sandbox/executor.js +537 -0
- package/dist/runtime/sandbox/index.d.ts +9 -0
- package/dist/runtime/sandbox/index.js +9 -0
- package/dist/runtime/sandbox/io-monitor.d.ts +78 -0
- package/dist/runtime/sandbox/io-monitor.js +98 -0
- package/dist/runtime/sandbox/time-parser.d.ts +19 -0
- package/dist/runtime/sandbox/time-parser.js +67 -0
- package/dist/runtime/sandbox/types.d.ts +58 -0
- package/dist/runtime/sandbox/types.js +23 -0
- package/dist/runtime/test/behavior-observer.d.ts +61 -0
- package/dist/runtime/test/behavior-observer.js +140 -0
- package/dist/runtime/test/contract-loader.d.ts +41 -0
- package/dist/runtime/test/contract-loader.js +158 -0
- package/dist/runtime/test/contract-schema.d.ts +46 -0
- package/dist/runtime/test/contract-schema.js +107 -0
- package/dist/runtime/test/contract-types.d.ts +106 -0
- package/dist/runtime/test/contract-types.js +6 -0
- package/dist/runtime/test/dependency-tracker.d.ts +66 -0
- package/dist/runtime/test/dependency-tracker.js +80 -0
- package/dist/runtime/test/formatters.d.ts +18 -0
- package/dist/runtime/test/formatters.js +172 -0
- package/dist/runtime/test/index.d.ts +12 -0
- package/dist/runtime/test/index.js +13 -0
- package/dist/runtime/test/input-generator.d.ts +33 -0
- package/dist/runtime/test/input-generator.js +498 -0
- package/dist/runtime/test/mcp-root-detector.d.ts +31 -0
- package/dist/runtime/test/mcp-root-detector.js +105 -0
- package/dist/runtime/test/orchestrator.d.ts +131 -0
- package/dist/runtime/test/orchestrator.js +738 -0
- package/dist/runtime/test/output-validator.d.ts +44 -0
- package/dist/runtime/test/output-validator.js +262 -0
- package/dist/runtime/test/retry-tester.d.ts +44 -0
- package/dist/runtime/test/retry-tester.js +103 -0
- package/dist/runtime/test/runner.d.ts +28 -0
- package/dist/runtime/test/runner.js +55 -0
- package/dist/runtime/test/synthetic-input-generator.d.ts +11 -0
- package/dist/runtime/test/synthetic-input-generator.js +154 -0
- package/dist/runtime/test/test-runner.d.ts +28 -0
- package/dist/runtime/test/test-runner.js +55 -0
- package/dist/types/factories.d.ts +16 -0
- package/dist/types/factories.js +43 -0
- package/dist/types/ids.d.ts +16 -0
- package/dist/types/ids.js +2 -0
- package/dist/types/opaque.d.ts +4 -0
- package/dist/types/opaque.js +2 -0
- package/dist/utils/errors.d.ts +92 -0
- package/dist/utils/errors.js +97 -0
- package/dist/utils/gitignore.d.ts +11 -0
- package/dist/utils/gitignore.js +59 -0
- package/dist/utils/json-file-saver.d.ts +17 -0
- package/dist/utils/json-file-saver.js +81 -0
- package/dist/utils/json-formatter.d.ts +63 -0
- package/dist/utils/json-formatter.js +344 -0
- package/dist/utils/logger.d.ts +184 -0
- package/dist/utils/logger.js +330 -0
- package/dist/utils/package-manager.d.ts +30 -0
- package/dist/utils/package-manager.js +157 -0
- package/dist/utils/version-checker.d.ts +47 -0
- package/dist/utils/version-checker.js +167 -0
- package/dist/utils/version-display.d.ts +10 -0
- package/dist/utils/version-display.js +20 -0
- package/package.json +106 -0
|
@@ -0,0 +1,714 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat UI for Dev Mode using Ink (React for terminal UIs).
|
|
3
|
+
* Provides a ChatGPT-like terminal interface with message history and input panel.
|
|
4
|
+
*
|
|
5
|
+
* Note: React and Ink are dynamically imported to avoid ESM/CommonJS issues.
|
|
6
|
+
* The component is created inline using React.createElement to avoid separate module imports.
|
|
7
|
+
*
|
|
8
|
+
* ESLint warnings for dynamic imports and React.createElement are disabled as they are
|
|
9
|
+
* necessary for this approach to work with ESM modules in a CommonJS context.
|
|
10
|
+
*/
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import { wrapText } from './text-wrapper.js';
|
|
14
|
+
import { createHeader, createWelcomeBanner, createInputPanel, createMessageComponent, createMessagesList, } from './components/index.js';
|
|
15
|
+
import { generateGoodbyeMessage } from './goodbye-messages.js';
|
|
16
|
+
export class ChatUI {
|
|
17
|
+
options;
|
|
18
|
+
instance = null;
|
|
19
|
+
addMessageRef;
|
|
20
|
+
updateLastAssistantMessageRef;
|
|
21
|
+
updateLastSystemMessageRef;
|
|
22
|
+
getMessagesRef;
|
|
23
|
+
clearMessagesRef;
|
|
24
|
+
getLastLargeDataMessageRef;
|
|
25
|
+
constructor(options) {
|
|
26
|
+
this.options = options;
|
|
27
|
+
// Initialize refs as mutable ref objects (will be populated when component mounts)
|
|
28
|
+
this.addMessageRef = { current: () => { } };
|
|
29
|
+
this.updateLastAssistantMessageRef = {
|
|
30
|
+
current: () => { },
|
|
31
|
+
};
|
|
32
|
+
this.updateLastSystemMessageRef = {
|
|
33
|
+
current: () => { },
|
|
34
|
+
};
|
|
35
|
+
this.getMessagesRef = {
|
|
36
|
+
current: () => [],
|
|
37
|
+
};
|
|
38
|
+
this.clearMessagesRef = {
|
|
39
|
+
current: () => { },
|
|
40
|
+
};
|
|
41
|
+
this.getLastLargeDataMessageRef = {
|
|
42
|
+
current: () => null,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async start() {
|
|
46
|
+
// Dynamically import React and Ink (ESM modules)
|
|
47
|
+
// Use Function constructor to preserve import() syntax and avoid TypeScript transpilation to require()
|
|
48
|
+
const importDynamic = new Function('specifier', 'return import(specifier)');
|
|
49
|
+
const [ReactModule, inkModule, textInputModule] = await Promise.all([
|
|
50
|
+
importDynamic('react'),
|
|
51
|
+
importDynamic('ink'),
|
|
52
|
+
importDynamic('ink-text-input'),
|
|
53
|
+
]);
|
|
54
|
+
const React = ReactModule.default || ReactModule;
|
|
55
|
+
const { useState, useEffect, useCallback, useRef, memo } = React;
|
|
56
|
+
const { Box, Text, useApp, useInput, render } = inkModule;
|
|
57
|
+
const TextInput = textInputModule.default;
|
|
58
|
+
// Capture options and refs for use inside the component
|
|
59
|
+
const options = this.options;
|
|
60
|
+
const addMessageRef = this.addMessageRef;
|
|
61
|
+
const updateLastAssistantMessageRef = this.updateLastAssistantMessageRef;
|
|
62
|
+
const updateLastSystemMessageRef = this.updateLastSystemMessageRef;
|
|
63
|
+
const getMessagesRef = this.getMessagesRef;
|
|
64
|
+
const clearMessagesRef = this.clearMessagesRef;
|
|
65
|
+
const getLastLargeDataMessageRef = this.getLastLargeDataMessageRef;
|
|
66
|
+
// Create the component inline to avoid importing a separate module file
|
|
67
|
+
// This avoids top-level require() calls for ESM modules
|
|
68
|
+
const ChatUIComponent = () => {
|
|
69
|
+
const { exit } = useApp();
|
|
70
|
+
const [messages, setMessages] = useState([]);
|
|
71
|
+
const [input, setInput] = useState('');
|
|
72
|
+
const [isProcessing, setIsProcessing] = useState(false);
|
|
73
|
+
const maxHistorySize = options.maxHistorySize || 1000;
|
|
74
|
+
// Viewport limiting: only show last N messages for performance
|
|
75
|
+
const maxVisibleMessages = 50; // Show last 50 messages by default
|
|
76
|
+
const inputHistoryRef = useRef([]);
|
|
77
|
+
const historyIndexRef = useRef(-1);
|
|
78
|
+
const currentInputRef = useRef('');
|
|
79
|
+
// Cache for parsed markdown to avoid re-parsing on every render
|
|
80
|
+
const markdownCacheRef = useRef(new Map());
|
|
81
|
+
// Load history from file on mount
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (options.historyFile) {
|
|
84
|
+
try {
|
|
85
|
+
if (fs.existsSync(options.historyFile)) {
|
|
86
|
+
const content = fs.readFileSync(options.historyFile, 'utf-8');
|
|
87
|
+
const loadedHistory = content
|
|
88
|
+
.split('\n')
|
|
89
|
+
.filter((line) => line.trim())
|
|
90
|
+
.slice(-maxHistorySize); // Only keep last N entries
|
|
91
|
+
inputHistoryRef.current = loadedHistory;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Ignore errors loading history
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}, []); // Only run on mount
|
|
99
|
+
// Save history to file helper
|
|
100
|
+
const saveHistoryToFile = useCallback(() => {
|
|
101
|
+
if (options.historyFile && inputHistoryRef.current.length > 0) {
|
|
102
|
+
try {
|
|
103
|
+
const dir = path.dirname(options.historyFile);
|
|
104
|
+
if (!fs.existsSync(dir)) {
|
|
105
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
106
|
+
}
|
|
107
|
+
fs.writeFileSync(options.historyFile, inputHistoryRef.current.join('\n') + '\n', 'utf-8');
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Ignore errors saving history
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}, [options.historyFile]); // Only depend on historyFile, not the ref
|
|
114
|
+
// Initialize messages
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
if (options.initialMessages && options.initialMessages.length > 0) {
|
|
117
|
+
const initMsgs = options.initialMessages.map(msg => ({
|
|
118
|
+
...msg,
|
|
119
|
+
timestamp: new Date(),
|
|
120
|
+
}));
|
|
121
|
+
setMessages(initMsgs);
|
|
122
|
+
}
|
|
123
|
+
}, []); // Only run on mount
|
|
124
|
+
// Expose methods via refs - use useCallback for stable references
|
|
125
|
+
const addMessage = useCallback((role, content, largeData) => {
|
|
126
|
+
setMessages((prev) => [
|
|
127
|
+
...prev,
|
|
128
|
+
{ role, content, timestamp: new Date(), largeData },
|
|
129
|
+
]);
|
|
130
|
+
}, []);
|
|
131
|
+
const updateLastAssistantMessage = useCallback((content) => {
|
|
132
|
+
setMessages((prev) => {
|
|
133
|
+
const newMessages = [...prev];
|
|
134
|
+
const lastIndex = newMessages.length - 1;
|
|
135
|
+
if (lastIndex >= 0 &&
|
|
136
|
+
newMessages[lastIndex]?.role === 'assistant') {
|
|
137
|
+
newMessages[lastIndex] = {
|
|
138
|
+
...newMessages[lastIndex],
|
|
139
|
+
content,
|
|
140
|
+
timestamp: newMessages[lastIndex]?.timestamp || new Date(),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
newMessages.push({
|
|
145
|
+
role: 'assistant',
|
|
146
|
+
content,
|
|
147
|
+
timestamp: new Date(),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return newMessages;
|
|
151
|
+
});
|
|
152
|
+
}, []);
|
|
153
|
+
const updateLastSystemMessage = useCallback((content) => {
|
|
154
|
+
setMessages((prev) => {
|
|
155
|
+
const newMessages = [...prev];
|
|
156
|
+
const lastIndex = newMessages.length - 1;
|
|
157
|
+
if (lastIndex >= 0 && newMessages[lastIndex]?.role === 'system') {
|
|
158
|
+
newMessages[lastIndex] = {
|
|
159
|
+
...newMessages[lastIndex],
|
|
160
|
+
content,
|
|
161
|
+
timestamp: newMessages[lastIndex]?.timestamp || new Date(),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
newMessages.push({
|
|
166
|
+
role: 'system',
|
|
167
|
+
content,
|
|
168
|
+
timestamp: new Date(),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
return newMessages;
|
|
172
|
+
});
|
|
173
|
+
}, []);
|
|
174
|
+
const getMessages = useCallback(() => {
|
|
175
|
+
return messages;
|
|
176
|
+
}, [messages]);
|
|
177
|
+
const getLastLargeDataMessage = useCallback(() => {
|
|
178
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
179
|
+
const msg = messages[i];
|
|
180
|
+
if (msg && msg.largeData) {
|
|
181
|
+
return msg;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return null;
|
|
185
|
+
}, [messages]);
|
|
186
|
+
const clearMessages = useCallback(() => {
|
|
187
|
+
setMessages([]);
|
|
188
|
+
}, []);
|
|
189
|
+
// Update refs only when callbacks change (which is stable due to useCallback)
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
addMessageRef.current = addMessage;
|
|
192
|
+
updateLastAssistantMessageRef.current = updateLastAssistantMessage;
|
|
193
|
+
updateLastSystemMessageRef.current = updateLastSystemMessage;
|
|
194
|
+
getMessagesRef.current = getMessages;
|
|
195
|
+
clearMessagesRef.current = clearMessages;
|
|
196
|
+
getLastLargeDataMessageRef.current = getLastLargeDataMessage;
|
|
197
|
+
}, [
|
|
198
|
+
addMessage,
|
|
199
|
+
updateLastAssistantMessage,
|
|
200
|
+
updateLastSystemMessage,
|
|
201
|
+
getMessages,
|
|
202
|
+
clearMessages,
|
|
203
|
+
getLastLargeDataMessage,
|
|
204
|
+
]);
|
|
205
|
+
// Helper to show goodbye message and exit
|
|
206
|
+
const showGoodbyeAndExit = useCallback(async () => {
|
|
207
|
+
try {
|
|
208
|
+
// Get session state if available
|
|
209
|
+
const sessionState = options.getSessionState?.();
|
|
210
|
+
if (sessionState) {
|
|
211
|
+
// Generate goodbye message
|
|
212
|
+
// Map toolCalls to match DevSessionState format
|
|
213
|
+
const fullSessionState = {
|
|
214
|
+
totalToolCalls: sessionState.totalToolCalls,
|
|
215
|
+
toolCalls: sessionState.toolCalls.map(tc => ({
|
|
216
|
+
id: '',
|
|
217
|
+
name: tc.name,
|
|
218
|
+
arguments: {},
|
|
219
|
+
timestamp: tc.timestamp,
|
|
220
|
+
})),
|
|
221
|
+
startTime: sessionState.startTime,
|
|
222
|
+
conversationHistory: [],
|
|
223
|
+
totalLLMCalls: 0,
|
|
224
|
+
};
|
|
225
|
+
const goodbyeMessage = await generateGoodbyeMessage(options.llmProvider || null, fullSessionState);
|
|
226
|
+
// Add goodbye message to chat
|
|
227
|
+
setMessages((prev) => [
|
|
228
|
+
...prev,
|
|
229
|
+
{
|
|
230
|
+
role: 'assistant',
|
|
231
|
+
content: goodbyeMessage,
|
|
232
|
+
timestamp: new Date(),
|
|
233
|
+
},
|
|
234
|
+
]);
|
|
235
|
+
// Wait a bit for message to be displayed
|
|
236
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
// Ignore errors during goodbye message generation
|
|
241
|
+
console.error('Error generating goodbye message:', error);
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
await options.onExit?.();
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// Ignore errors during exit
|
|
248
|
+
}
|
|
249
|
+
exit();
|
|
250
|
+
}, [options, exit, setMessages]);
|
|
251
|
+
// Handle special commands
|
|
252
|
+
// Returns true if the command was handled, false if it should be passed to onMessage
|
|
253
|
+
const handleSpecialCommand = useCallback(async (command) => {
|
|
254
|
+
const parts = command.split(/\s+/);
|
|
255
|
+
const cmd = parts[0]?.toLowerCase();
|
|
256
|
+
switch (cmd) {
|
|
257
|
+
case '/exit':
|
|
258
|
+
case '/quit':
|
|
259
|
+
// Show goodbye and exit (user message already added by handleSubmit)
|
|
260
|
+
await showGoodbyeAndExit();
|
|
261
|
+
return true;
|
|
262
|
+
case '/clear':
|
|
263
|
+
setMessages([]);
|
|
264
|
+
return true;
|
|
265
|
+
case '/help':
|
|
266
|
+
setMessages((prev) => [
|
|
267
|
+
...prev,
|
|
268
|
+
{
|
|
269
|
+
role: 'system',
|
|
270
|
+
content: 'Available commands:\n' +
|
|
271
|
+
' /help - Show this help message\n' +
|
|
272
|
+
' /clear - Clear the chat history\n' +
|
|
273
|
+
' /tools - List available MCP tools\n' +
|
|
274
|
+
' /history - Show command history\n' +
|
|
275
|
+
' /save-json [tool-name-or-index] - Save tool result JSON to file\n' +
|
|
276
|
+
' (no arg = last result, number = by index, name = by name)\n' +
|
|
277
|
+
' /exit, /quit - Exit the chat',
|
|
278
|
+
timestamp: new Date(),
|
|
279
|
+
},
|
|
280
|
+
]);
|
|
281
|
+
return true;
|
|
282
|
+
default:
|
|
283
|
+
// Not a UI-level special command, pass to onMessage callback
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
}, [options, showGoodbyeAndExit]);
|
|
287
|
+
// Handle input submission
|
|
288
|
+
const handleSubmit = useCallback((value) => {
|
|
289
|
+
void (async () => {
|
|
290
|
+
const trimmedValue = value.trim();
|
|
291
|
+
if (!trimmedValue)
|
|
292
|
+
return;
|
|
293
|
+
// Clear input immediately
|
|
294
|
+
setInput('');
|
|
295
|
+
// Save current input before checking for special commands
|
|
296
|
+
currentInputRef.current = '';
|
|
297
|
+
// Add user message to chat
|
|
298
|
+
setMessages((prev) => [
|
|
299
|
+
...prev,
|
|
300
|
+
{ role: 'user', content: trimmedValue, timestamp: new Date() },
|
|
301
|
+
]);
|
|
302
|
+
// Save to history FIRST (before handling commands) - ensures all commands are saved
|
|
303
|
+
// Move existing prompt to recent position if duplicate (don't repeat)
|
|
304
|
+
if (trimmedValue) {
|
|
305
|
+
const history = inputHistoryRef.current;
|
|
306
|
+
// Remove duplicate if exists (this moves it to end)
|
|
307
|
+
const filtered = history.filter((h) => h !== trimmedValue);
|
|
308
|
+
// Add to end (most recent)
|
|
309
|
+
filtered.push(trimmedValue);
|
|
310
|
+
// Keep only last N entries
|
|
311
|
+
inputHistoryRef.current = filtered.slice(-maxHistorySize);
|
|
312
|
+
// Save to file
|
|
313
|
+
saveHistoryToFile();
|
|
314
|
+
}
|
|
315
|
+
// Reset history navigation
|
|
316
|
+
historyIndexRef.current = -1;
|
|
317
|
+
// Handle UI-level special commands (only if handled by UI)
|
|
318
|
+
if (trimmedValue.startsWith('/')) {
|
|
319
|
+
const wasHandled = await handleSpecialCommand(trimmedValue);
|
|
320
|
+
if (wasHandled) {
|
|
321
|
+
return; // Command was handled by UI, don't pass to onMessage
|
|
322
|
+
}
|
|
323
|
+
// Command was not handled by UI, continue to pass to onMessage callback
|
|
324
|
+
}
|
|
325
|
+
// Process the message
|
|
326
|
+
setIsProcessing(true);
|
|
327
|
+
try {
|
|
328
|
+
await options.onMessage?.(trimmedValue);
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
setMessages((prev) => [
|
|
332
|
+
...prev,
|
|
333
|
+
{
|
|
334
|
+
role: 'system',
|
|
335
|
+
content: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
336
|
+
timestamp: new Date(),
|
|
337
|
+
},
|
|
338
|
+
]);
|
|
339
|
+
}
|
|
340
|
+
finally {
|
|
341
|
+
setIsProcessing(false);
|
|
342
|
+
}
|
|
343
|
+
})();
|
|
344
|
+
}, [options, handleSpecialCommand, maxHistorySize, saveHistoryToFile]);
|
|
345
|
+
// Handle Ctrl+C (always active)
|
|
346
|
+
useInput((_char, key) => {
|
|
347
|
+
if ((key.ctrl && _char === 'c') || _char === '\x03' || key.escape) {
|
|
348
|
+
void (async () => {
|
|
349
|
+
// Add user message showing they pressed Ctrl+C
|
|
350
|
+
setMessages((prev) => [
|
|
351
|
+
...prev,
|
|
352
|
+
{ role: 'user', content: '/exit', timestamp: new Date() },
|
|
353
|
+
]);
|
|
354
|
+
// Show goodbye and exit
|
|
355
|
+
await showGoodbyeAndExit();
|
|
356
|
+
})();
|
|
357
|
+
}
|
|
358
|
+
}, { isActive: true });
|
|
359
|
+
// Handle arrow keys for history navigation (only when not processing)
|
|
360
|
+
useInput((_char, key) => {
|
|
361
|
+
if (key.upArrow || key.downArrow) {
|
|
362
|
+
if (inputHistoryRef.current.length === 0 || isProcessing) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
if (key.upArrow) {
|
|
366
|
+
// Save current input if we're starting navigation
|
|
367
|
+
if (historyIndexRef.current === -1) {
|
|
368
|
+
currentInputRef.current = input;
|
|
369
|
+
}
|
|
370
|
+
// Move up in history
|
|
371
|
+
historyIndexRef.current = Math.min(historyIndexRef.current + 1, inputHistoryRef.current.length - 1);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
// Move down in history
|
|
375
|
+
historyIndexRef.current = Math.max(historyIndexRef.current - 1, -1);
|
|
376
|
+
}
|
|
377
|
+
// Set input from history or restore current
|
|
378
|
+
if (historyIndexRef.current >= 0) {
|
|
379
|
+
const historyItem = inputHistoryRef.current[inputHistoryRef.current.length - 1 - historyIndexRef.current];
|
|
380
|
+
if (historyItem !== undefined) {
|
|
381
|
+
setInput(historyItem);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
setInput(currentInputRef.current);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}, { isActive: !isProcessing });
|
|
389
|
+
// Note: Ctrl+C is now handled in useInput hook above
|
|
390
|
+
// The useInput hook intercepts all input including Ctrl+C, so SIGINT won't fire
|
|
391
|
+
// We handle Ctrl+C directly in the useInput callback
|
|
392
|
+
// Parse inline markdown (bold, italic, code) - kept in main file due to React hooks
|
|
393
|
+
const parseInlineMarkdown = useCallback((text, baseKey, defaultColor) => {
|
|
394
|
+
const elements = [];
|
|
395
|
+
const parts = text.split(/(\*\*[^*]+\*\*|\*[^*]+\*|``[^`]+``|`[^`]+`)/g);
|
|
396
|
+
let keyIndex = 0;
|
|
397
|
+
for (const part of parts) {
|
|
398
|
+
if (!part)
|
|
399
|
+
continue;
|
|
400
|
+
// Bold **text**
|
|
401
|
+
if (part.startsWith('**') && part.endsWith('**')) {
|
|
402
|
+
const content = part.slice(2, -2);
|
|
403
|
+
elements.push(React.createElement(Text, {
|
|
404
|
+
key: baseKey * 100 + keyIndex++,
|
|
405
|
+
bold: true,
|
|
406
|
+
...(defaultColor ? { color: defaultColor } : {}),
|
|
407
|
+
}, content));
|
|
408
|
+
}
|
|
409
|
+
// Italic *text*
|
|
410
|
+
else if (part.startsWith('*') &&
|
|
411
|
+
part.endsWith('*') &&
|
|
412
|
+
!part.startsWith('**')) {
|
|
413
|
+
const content = part.slice(1, -1);
|
|
414
|
+
elements.push(React.createElement(Text, {
|
|
415
|
+
key: baseKey * 100 + keyIndex++,
|
|
416
|
+
dimColor: true,
|
|
417
|
+
...(defaultColor ? { color: defaultColor } : {}),
|
|
418
|
+
}, content));
|
|
419
|
+
}
|
|
420
|
+
// Command ``text`` (double backticks - styled differently)
|
|
421
|
+
else if (part.startsWith('``') && part.endsWith('``')) {
|
|
422
|
+
const content = part.slice(2, -2);
|
|
423
|
+
elements.push(React.createElement(Text, {
|
|
424
|
+
key: baseKey * 100 + keyIndex++,
|
|
425
|
+
color: 'green',
|
|
426
|
+
bold: true,
|
|
427
|
+
}, content));
|
|
428
|
+
}
|
|
429
|
+
// Code `text` (single backtick - tool names, etc.)
|
|
430
|
+
else if (part.startsWith('`') && part.endsWith('`')) {
|
|
431
|
+
const content = part.slice(1, -1);
|
|
432
|
+
elements.push(React.createElement(Text, {
|
|
433
|
+
key: baseKey * 100 + keyIndex++,
|
|
434
|
+
color: 'cyan',
|
|
435
|
+
}, content));
|
|
436
|
+
}
|
|
437
|
+
// Regular text
|
|
438
|
+
else {
|
|
439
|
+
elements.push(React.createElement(Text, {
|
|
440
|
+
key: baseKey * 100 + keyIndex++,
|
|
441
|
+
...(defaultColor
|
|
442
|
+
? {
|
|
443
|
+
color: defaultColor,
|
|
444
|
+
...(defaultColor === 'yellow'
|
|
445
|
+
? {}
|
|
446
|
+
: { dimColor: true }),
|
|
447
|
+
}
|
|
448
|
+
: {}),
|
|
449
|
+
}, part));
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return elements;
|
|
453
|
+
}, []);
|
|
454
|
+
// Parse table markdown
|
|
455
|
+
const parseTable = useCallback((rows, baseKey, defaultColor) => {
|
|
456
|
+
if (rows.length === 0)
|
|
457
|
+
return null;
|
|
458
|
+
const parsedRows = rows
|
|
459
|
+
.map(row => {
|
|
460
|
+
const cells = row
|
|
461
|
+
.split('|')
|
|
462
|
+
.map(cell => cell.trim())
|
|
463
|
+
.filter(cell => cell.length > 0);
|
|
464
|
+
return cells;
|
|
465
|
+
})
|
|
466
|
+
.filter(row => row.length > 0);
|
|
467
|
+
if (parsedRows.length === 0)
|
|
468
|
+
return null;
|
|
469
|
+
const dataRows = parsedRows.filter((row, idx) => idx !== 1 || !row.every(cell => /^-+$/.test(cell)));
|
|
470
|
+
if (dataRows.length === 0)
|
|
471
|
+
return null;
|
|
472
|
+
const headerRow = dataRows[0] || [];
|
|
473
|
+
const bodyRows = dataRows.slice(1);
|
|
474
|
+
return React.createElement(Box, { key: baseKey, flexDirection: 'column', marginY: 1 }, React.createElement(Box, { key: 'header', flexDirection: 'row', marginBottom: 0.5 }, ...headerRow.map((cell, idx) => React.createElement(Box, {
|
|
475
|
+
key: idx,
|
|
476
|
+
paddingX: 1,
|
|
477
|
+
minWidth: Math.floor(80 / headerRow.length),
|
|
478
|
+
}, ...parseInlineMarkdown(cell, baseKey * 1000 + idx, defaultColor)))), React.createElement(Box, { key: 'separator', marginY: 0.5 }, React.createElement(Text, { dimColor: true }, '─'.repeat(60))), ...bodyRows.map((row, rowIdx) => React.createElement(Box, { key: rowIdx, flexDirection: 'row', marginBottom: 0.25 }, ...row.map((cell, cellIdx) => React.createElement(Box, {
|
|
479
|
+
key: cellIdx,
|
|
480
|
+
paddingX: 1,
|
|
481
|
+
minWidth: Math.floor(80 / headerRow.length),
|
|
482
|
+
}, ...parseInlineMarkdown(cell, baseKey * 10000 + rowIdx * 100 + cellIdx, defaultColor))))));
|
|
483
|
+
}, [parseInlineMarkdown]);
|
|
484
|
+
// Markdown parser for formatting assistant/system messages
|
|
485
|
+
const parseMarkdown = useCallback((text, defaultColor) => {
|
|
486
|
+
const cacheKey = `${text}-${defaultColor || ''}`;
|
|
487
|
+
const cached = markdownCacheRef.current.get(cacheKey);
|
|
488
|
+
if (cached) {
|
|
489
|
+
return cached;
|
|
490
|
+
}
|
|
491
|
+
const elements = [];
|
|
492
|
+
let elementKey = 0;
|
|
493
|
+
const lines = text.split('\n');
|
|
494
|
+
let i = 0;
|
|
495
|
+
while (i < lines.length) {
|
|
496
|
+
const line = lines[i] || '';
|
|
497
|
+
if (line.trim().startsWith('```')) {
|
|
498
|
+
const languageMatch = line.trim().match(/^```(\w+)?$/);
|
|
499
|
+
const language = languageMatch?.[1] || '';
|
|
500
|
+
const codeLines = [];
|
|
501
|
+
i++;
|
|
502
|
+
while (i < lines.length) {
|
|
503
|
+
const codeLine = lines[i] || '';
|
|
504
|
+
if (codeLine.trim() === '```') {
|
|
505
|
+
i++;
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
codeLines.push(codeLine);
|
|
509
|
+
i++;
|
|
510
|
+
}
|
|
511
|
+
const codeColor = language === 'json' ? 'green' : 'white';
|
|
512
|
+
elements.push(React.createElement(Box, {
|
|
513
|
+
key: elementKey++,
|
|
514
|
+
flexDirection: 'column',
|
|
515
|
+
marginY: 0.5,
|
|
516
|
+
marginLeft: 2,
|
|
517
|
+
}, ...codeLines.map((codeLine, lineIdx) => React.createElement(Text, { key: lineIdx, color: codeColor }, codeLine))));
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
if (line.trim().startsWith('|') && line.includes('|')) {
|
|
521
|
+
const tableRows = [line];
|
|
522
|
+
i++;
|
|
523
|
+
while (i < lines.length) {
|
|
524
|
+
const nextLine = lines[i] || '';
|
|
525
|
+
if (nextLine.trim().startsWith('|') && nextLine.includes('|')) {
|
|
526
|
+
tableRows.push(nextLine);
|
|
527
|
+
i++;
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
const tableElement = parseTable(tableRows, elementKey++, defaultColor);
|
|
534
|
+
if (tableElement) {
|
|
535
|
+
elements.push(tableElement);
|
|
536
|
+
}
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
if (/^\s*\d+[.)]\s+/.test(line)) {
|
|
540
|
+
const listItems = [];
|
|
541
|
+
while (i < lines.length) {
|
|
542
|
+
const listLine = lines[i] || '';
|
|
543
|
+
if (/^\s*\d+[.)]\s+/.test(listLine)) {
|
|
544
|
+
listItems.push(listLine.replace(/^\s*\d+[.)]\s+/, ''));
|
|
545
|
+
i++;
|
|
546
|
+
}
|
|
547
|
+
else if (listLine.trim() === '') {
|
|
548
|
+
i++;
|
|
549
|
+
if (i < lines.length &&
|
|
550
|
+
/^\s*\d+[.)]\s+/.test(lines[i] || '')) {
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
break;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
elements.push(React.createElement(Box, { key: elementKey++, flexDirection: 'column', marginY: 0.5 }, ...listItems.map((item, idx) => React.createElement(Box, { key: idx, marginLeft: 2, marginBottom: 0.25 }, React.createElement(Text, {
|
|
560
|
+
...(defaultColor
|
|
561
|
+
? {
|
|
562
|
+
color: defaultColor,
|
|
563
|
+
...(defaultColor === 'yellow'
|
|
564
|
+
? {}
|
|
565
|
+
: { dimColor: true }),
|
|
566
|
+
}
|
|
567
|
+
: {}),
|
|
568
|
+
}, `${idx + 1}. `), ...parseInlineMarkdown(item, elementKey * 1000 + idx, defaultColor)))));
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
if (/^\s*[-*]\s+/.test(line)) {
|
|
572
|
+
const listItems = [];
|
|
573
|
+
while (i < lines.length) {
|
|
574
|
+
const listLine = lines[i] || '';
|
|
575
|
+
if (/^\s*[-*]\s+/.test(listLine)) {
|
|
576
|
+
listItems.push(listLine.replace(/^\s*[-*]\s+/, ''));
|
|
577
|
+
i++;
|
|
578
|
+
}
|
|
579
|
+
else if (listLine.trim() === '') {
|
|
580
|
+
i++;
|
|
581
|
+
if (i < lines.length && /^\s*[-*]\s+/.test(lines[i] || '')) {
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
break;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
elements.push(React.createElement(Box, { key: elementKey++, flexDirection: 'column', marginY: 0.5 }, ...listItems.map((item, idx) => React.createElement(Box, { key: idx, marginLeft: 2, marginBottom: 0.25 }, React.createElement(Text, {
|
|
591
|
+
...(defaultColor
|
|
592
|
+
? {
|
|
593
|
+
color: defaultColor,
|
|
594
|
+
...(defaultColor === 'yellow'
|
|
595
|
+
? {}
|
|
596
|
+
: { dimColor: true }),
|
|
597
|
+
}
|
|
598
|
+
: {}),
|
|
599
|
+
}, '• '), ...parseInlineMarkdown(item, elementKey * 1000 + idx, defaultColor)))));
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
if (line.trim()) {
|
|
603
|
+
const inlineElements = parseInlineMarkdown(line, elementKey++, defaultColor);
|
|
604
|
+
elements.push(React.createElement(Box, {
|
|
605
|
+
key: elementKey - 1,
|
|
606
|
+
flexDirection: 'row',
|
|
607
|
+
flexWrap: 'wrap',
|
|
608
|
+
}, ...inlineElements));
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
elements.push(React.createElement(Box, {
|
|
612
|
+
key: elementKey++,
|
|
613
|
+
height: 1,
|
|
614
|
+
}));
|
|
615
|
+
}
|
|
616
|
+
i++;
|
|
617
|
+
}
|
|
618
|
+
markdownCacheRef.current.set(cacheKey, elements);
|
|
619
|
+
if (markdownCacheRef.current.size > 100) {
|
|
620
|
+
const firstKey = markdownCacheRef.current.keys().next().value;
|
|
621
|
+
if (firstKey) {
|
|
622
|
+
markdownCacheRef.current.delete(firstKey);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return elements;
|
|
626
|
+
}, [parseInlineMarkdown, parseTable]);
|
|
627
|
+
// Create message component using extracted factory
|
|
628
|
+
const createMessageComponentFn = createMessageComponent(React, Box, Text, memo);
|
|
629
|
+
const MessageComponent = createMessageComponentFn(parseMarkdown, wrapText);
|
|
630
|
+
// Render using React.createElement (can't use JSX here without importing React at top level)
|
|
631
|
+
return React.createElement(Box, {
|
|
632
|
+
flexDirection: 'column',
|
|
633
|
+
width: '100%',
|
|
634
|
+
height: '100%',
|
|
635
|
+
},
|
|
636
|
+
// Header - distinct style with blue background and border
|
|
637
|
+
createHeader(React, Box, Text),
|
|
638
|
+
// Welcome banner - persistent, not cleared by /clear
|
|
639
|
+
options.welcomeBanner
|
|
640
|
+
? createWelcomeBanner(React, Box, Text, options.welcomeBanner)
|
|
641
|
+
: null,
|
|
642
|
+
// Messages area - scrollable, takes remaining space (allows terminal scrolling)
|
|
643
|
+
createMessagesList(React, Box, Text, messages, maxVisibleMessages, MessageComponent, options),
|
|
644
|
+
// Input area - fixed at bottom, modern minimal design with border and black background
|
|
645
|
+
// flexShrink: 0 ensures it never shrinks, keeping it always visible at bottom
|
|
646
|
+
createInputPanel(React, Box, Text, TextInput, options, input, isProcessing, setInput, handleSubmit));
|
|
647
|
+
};
|
|
648
|
+
// Render the component with full screen options
|
|
649
|
+
this.instance = render(React.createElement(ChatUIComponent), {
|
|
650
|
+
stdout: process.stdout,
|
|
651
|
+
stderr: process.stderr,
|
|
652
|
+
stdin: process.stdin,
|
|
653
|
+
exitOnCtrlC: false, // We handle this manually
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Add a message to the chat.
|
|
658
|
+
*/
|
|
659
|
+
addMessage(role, content) {
|
|
660
|
+
this.addMessageRef.current(role, content);
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Add a message with large data reference.
|
|
664
|
+
*/
|
|
665
|
+
addMessageWithData(role, content, largeData) {
|
|
666
|
+
this.addMessageRef.current(role, content, largeData);
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Get the last message with large data.
|
|
670
|
+
*/
|
|
671
|
+
getLastLargeDataMessage() {
|
|
672
|
+
return this.getLastLargeDataMessageRef.current();
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Update the last assistant message (for streaming).
|
|
676
|
+
*/
|
|
677
|
+
updateLastAssistantMessage(content) {
|
|
678
|
+
this.updateLastAssistantMessageRef.current(content);
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Update the last system message (for live updates like waiting indicators).
|
|
682
|
+
*/
|
|
683
|
+
updateLastSystemMessage(content) {
|
|
684
|
+
this.updateLastSystemMessageRef.current(content);
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Get all messages.
|
|
688
|
+
*/
|
|
689
|
+
getMessages() {
|
|
690
|
+
return this.getMessagesRef.current();
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Clear all messages.
|
|
694
|
+
*/
|
|
695
|
+
clearMessages() {
|
|
696
|
+
this.clearMessagesRef.current();
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Stop the chat UI (same as exit).
|
|
700
|
+
*/
|
|
701
|
+
stop() {
|
|
702
|
+
if (this.instance) {
|
|
703
|
+
this.instance.unmount();
|
|
704
|
+
this.instance = null;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Exit the chat UI.
|
|
709
|
+
*/
|
|
710
|
+
exit() {
|
|
711
|
+
this.stop();
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
//# sourceMappingURL=chat-ui.js.map
|