@portel/photon 1.4.1 → 1.6.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/README.md +326 -1177
- package/dist/auto-ui/beam.d.ts +14 -0
- package/dist/auto-ui/beam.d.ts.map +1 -0
- package/dist/auto-ui/beam.js +3057 -0
- package/dist/auto-ui/beam.js.map +1 -0
- package/dist/auto-ui/bridge/index.d.ts +37 -0
- package/dist/auto-ui/bridge/index.d.ts.map +1 -0
- package/dist/auto-ui/bridge/index.js +555 -0
- package/dist/auto-ui/bridge/index.js.map +1 -0
- package/dist/auto-ui/bridge/openai-shim.d.ts +20 -0
- package/dist/auto-ui/bridge/openai-shim.d.ts.map +1 -0
- package/dist/auto-ui/bridge/openai-shim.js +231 -0
- package/dist/auto-ui/bridge/openai-shim.js.map +1 -0
- package/dist/auto-ui/bridge/photon-app.d.ts +162 -0
- package/dist/auto-ui/bridge/photon-app.d.ts.map +1 -0
- package/dist/auto-ui/bridge/photon-app.js +460 -0
- package/dist/auto-ui/bridge/photon-app.js.map +1 -0
- package/dist/auto-ui/bridge/types.d.ts +128 -0
- package/dist/auto-ui/bridge/types.d.ts.map +1 -0
- package/dist/auto-ui/bridge/types.js +7 -0
- package/dist/auto-ui/bridge/types.js.map +1 -0
- package/dist/auto-ui/components/card.d.ts +13 -0
- package/dist/auto-ui/components/card.d.ts.map +1 -0
- package/dist/auto-ui/components/card.js +64 -0
- package/dist/auto-ui/components/card.js.map +1 -0
- package/dist/auto-ui/components/form.d.ts +15 -0
- package/dist/auto-ui/components/form.d.ts.map +1 -0
- package/dist/auto-ui/components/form.js +72 -0
- package/dist/auto-ui/components/form.js.map +1 -0
- package/dist/auto-ui/components/list.d.ts +13 -0
- package/dist/auto-ui/components/list.d.ts.map +1 -0
- package/dist/auto-ui/components/list.js +58 -0
- package/dist/auto-ui/components/list.js.map +1 -0
- package/dist/auto-ui/components/progress.d.ts +18 -0
- package/dist/auto-ui/components/progress.d.ts.map +1 -0
- package/dist/auto-ui/components/progress.js +125 -0
- package/dist/auto-ui/components/progress.js.map +1 -0
- package/dist/auto-ui/components/table.d.ts +13 -0
- package/dist/auto-ui/components/table.d.ts.map +1 -0
- package/dist/auto-ui/components/table.js +82 -0
- package/dist/auto-ui/components/table.js.map +1 -0
- package/dist/auto-ui/components/tree.d.ts +13 -0
- package/dist/auto-ui/components/tree.d.ts.map +1 -0
- package/dist/auto-ui/components/tree.js +61 -0
- package/dist/auto-ui/components/tree.js.map +1 -0
- package/dist/auto-ui/daemon-tools.d.ts +45 -0
- package/dist/auto-ui/daemon-tools.d.ts.map +1 -0
- package/dist/auto-ui/daemon-tools.js +580 -0
- package/dist/auto-ui/daemon-tools.js.map +1 -0
- package/dist/auto-ui/design-system/index.d.ts +21 -0
- package/dist/auto-ui/design-system/index.d.ts.map +1 -0
- package/dist/auto-ui/design-system/index.js +27 -0
- package/dist/auto-ui/design-system/index.js.map +1 -0
- package/dist/auto-ui/design-system/tokens.d.ts +9 -0
- package/dist/auto-ui/design-system/tokens.d.ts.map +1 -0
- package/dist/auto-ui/design-system/tokens.js +27 -0
- package/dist/auto-ui/design-system/tokens.js.map +1 -0
- package/dist/auto-ui/design-system/transaction-ui.d.ts +70 -0
- package/dist/auto-ui/design-system/transaction-ui.d.ts.map +1 -0
- package/dist/auto-ui/design-system/transaction-ui.js +982 -0
- package/dist/auto-ui/design-system/transaction-ui.js.map +1 -0
- package/dist/auto-ui/frontend/index.html +84 -0
- package/dist/auto-ui/index.d.ts +23 -0
- package/dist/auto-ui/index.d.ts.map +1 -0
- package/dist/auto-ui/index.js +28 -0
- package/dist/auto-ui/index.js.map +1 -0
- package/dist/auto-ui/openapi-generator.d.ts +71 -0
- package/dist/auto-ui/openapi-generator.d.ts.map +1 -0
- package/dist/auto-ui/openapi-generator.js +223 -0
- package/dist/auto-ui/openapi-generator.js.map +1 -0
- package/dist/auto-ui/photon-bridge.d.ts +159 -0
- package/dist/auto-ui/photon-bridge.d.ts.map +1 -0
- package/dist/auto-ui/photon-bridge.js +262 -0
- package/dist/auto-ui/photon-bridge.js.map +1 -0
- package/dist/auto-ui/photon-host.d.ts +113 -0
- package/dist/auto-ui/photon-host.d.ts.map +1 -0
- package/dist/auto-ui/photon-host.js +284 -0
- package/dist/auto-ui/photon-host.js.map +1 -0
- package/dist/auto-ui/platform-compat.d.ts +71 -0
- package/dist/auto-ui/platform-compat.d.ts.map +1 -0
- package/dist/auto-ui/platform-compat.js +628 -0
- package/dist/auto-ui/platform-compat.js.map +1 -0
- package/dist/auto-ui/playground-html.d.ts +15 -0
- package/dist/auto-ui/playground-html.d.ts.map +1 -0
- package/dist/auto-ui/playground-html.js +1113 -0
- package/dist/auto-ui/playground-html.js.map +1 -0
- package/dist/auto-ui/playground-server.d.ts +7 -0
- package/dist/auto-ui/playground-server.d.ts.map +1 -0
- package/dist/auto-ui/playground-server.js +840 -0
- package/dist/auto-ui/playground-server.js.map +1 -0
- package/dist/auto-ui/registry.d.ts +13 -0
- package/dist/auto-ui/registry.d.ts.map +1 -0
- package/dist/auto-ui/registry.js +62 -0
- package/dist/auto-ui/registry.js.map +1 -0
- package/dist/auto-ui/renderer.d.ts +14 -0
- package/dist/auto-ui/renderer.d.ts.map +1 -0
- package/dist/auto-ui/renderer.js +88 -0
- package/dist/auto-ui/renderer.js.map +1 -0
- package/dist/auto-ui/rendering/components.d.ts +29 -0
- package/dist/auto-ui/rendering/components.d.ts.map +1 -0
- package/dist/auto-ui/rendering/components.js +773 -0
- package/dist/auto-ui/rendering/components.js.map +1 -0
- package/dist/auto-ui/rendering/field-analyzer.d.ts +48 -0
- package/dist/auto-ui/rendering/field-analyzer.d.ts.map +1 -0
- package/dist/auto-ui/rendering/field-analyzer.js +270 -0
- package/dist/auto-ui/rendering/field-analyzer.js.map +1 -0
- package/dist/auto-ui/rendering/field-renderers.d.ts +64 -0
- package/dist/auto-ui/rendering/field-renderers.d.ts.map +1 -0
- package/dist/auto-ui/rendering/field-renderers.js +317 -0
- package/dist/auto-ui/rendering/field-renderers.js.map +1 -0
- package/dist/auto-ui/rendering/index.d.ts +28 -0
- package/dist/auto-ui/rendering/index.d.ts.map +1 -0
- package/dist/auto-ui/rendering/index.js +60 -0
- package/dist/auto-ui/rendering/index.js.map +1 -0
- package/dist/auto-ui/rendering/layout-selector.d.ts +48 -0
- package/dist/auto-ui/rendering/layout-selector.d.ts.map +1 -0
- package/dist/auto-ui/rendering/layout-selector.js +352 -0
- package/dist/auto-ui/rendering/layout-selector.js.map +1 -0
- package/dist/auto-ui/rendering/template-engine.d.ts +41 -0
- package/dist/auto-ui/rendering/template-engine.d.ts.map +1 -0
- package/dist/auto-ui/rendering/template-engine.js +238 -0
- package/dist/auto-ui/rendering/template-engine.js.map +1 -0
- package/dist/auto-ui/streamable-http-transport.d.ts +103 -0
- package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -0
- package/dist/auto-ui/streamable-http-transport.js +1875 -0
- package/dist/auto-ui/streamable-http-transport.js.map +1 -0
- package/dist/auto-ui/types.d.ts +384 -0
- package/dist/auto-ui/types.d.ts.map +1 -0
- package/dist/auto-ui/types.js +92 -0
- package/dist/auto-ui/types.js.map +1 -0
- package/dist/beam.bundle.js +63137 -0
- package/dist/beam.bundle.js.map +7 -0
- package/dist/claude-code-plugin.d.ts.map +1 -1
- package/dist/claude-code-plugin.js +30 -30
- package/dist/claude-code-plugin.js.map +1 -1
- package/dist/cli/commands/info.d.ts +11 -0
- package/dist/cli/commands/info.d.ts.map +1 -0
- package/dist/cli/commands/info.js +313 -0
- package/dist/cli/commands/info.js.map +1 -0
- package/dist/cli/commands/marketplace.d.ts +11 -0
- package/dist/cli/commands/marketplace.d.ts.map +1 -0
- package/dist/cli/commands/marketplace.js +198 -0
- package/dist/cli/commands/marketplace.js.map +1 -0
- package/dist/cli/commands/package-app.d.ts +9 -0
- package/dist/cli/commands/package-app.d.ts.map +1 -0
- package/dist/cli/commands/package-app.js +191 -0
- package/dist/cli/commands/package-app.js.map +1 -0
- package/dist/cli/commands/package.d.ts +11 -0
- package/dist/cli/commands/package.d.ts.map +1 -0
- package/dist/cli/commands/package.js +573 -0
- package/dist/cli/commands/package.js.map +1 -0
- package/dist/cli-alias.d.ts.map +1 -1
- package/dist/cli-alias.js +30 -28
- package/dist/cli-alias.js.map +1 -1
- package/dist/cli-formatter.d.ts +8 -24
- package/dist/cli-formatter.d.ts.map +1 -1
- package/dist/cli-formatter.js +8 -325
- package/dist/cli-formatter.js.map +1 -1
- package/dist/cli.d.ts +15 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1166 -1131
- package/dist/cli.js.map +1 -1
- package/dist/daemon/client.d.ts +84 -3
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +561 -11
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/manager.d.ts +51 -12
- package/dist/daemon/manager.d.ts.map +1 -1
- package/dist/daemon/manager.js +122 -61
- package/dist/daemon/manager.js.map +1 -1
- package/dist/daemon/protocol.d.ts +62 -6
- package/dist/daemon/protocol.d.ts.map +1 -1
- package/dist/daemon/protocol.js +76 -1
- package/dist/daemon/protocol.js.map +1 -1
- package/dist/daemon/server.d.ts +6 -6
- package/dist/daemon/server.js +743 -133
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/session-manager.d.ts +8 -1
- package/dist/daemon/session-manager.d.ts.map +1 -1
- package/dist/daemon/session-manager.js +32 -9
- package/dist/daemon/session-manager.js.map +1 -1
- package/dist/deploy/cloudflare.d.ts +12 -0
- package/dist/deploy/cloudflare.d.ts.map +1 -0
- package/dist/deploy/cloudflare.js +216 -0
- package/dist/deploy/cloudflare.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +191 -21
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +1186 -319
- package/dist/loader.js.map +1 -1
- package/dist/markdown-utils.d.ts +8 -0
- package/dist/markdown-utils.d.ts.map +1 -0
- package/dist/markdown-utils.js +63 -0
- package/dist/markdown-utils.js.map +1 -0
- package/dist/marketplace-manager.d.ts +10 -0
- package/dist/marketplace-manager.d.ts.map +1 -1
- package/dist/marketplace-manager.js +112 -28
- package/dist/marketplace-manager.js.map +1 -1
- package/dist/mcp-client.d.ts +9 -0
- package/dist/mcp-client.d.ts.map +1 -0
- package/dist/mcp-client.js +11 -0
- package/dist/mcp-client.js.map +1 -0
- package/dist/mcp-elicitation.d.ts +32 -0
- package/dist/mcp-elicitation.d.ts.map +1 -0
- package/dist/mcp-elicitation.js +26 -0
- package/dist/mcp-elicitation.js.map +1 -0
- package/dist/path-resolver.d.ts +9 -12
- package/dist/path-resolver.d.ts.map +1 -1
- package/dist/path-resolver.js +13 -43
- package/dist/path-resolver.js.map +1 -1
- package/dist/photon-cli-runner.d.ts.map +1 -1
- package/dist/photon-cli-runner.js +204 -77
- package/dist/photon-cli-runner.js.map +1 -1
- package/dist/photon-doc-extractor.d.ts +89 -0
- package/dist/photon-doc-extractor.d.ts.map +1 -1
- package/dist/photon-doc-extractor.js +560 -32
- package/dist/photon-doc-extractor.js.map +1 -1
- package/dist/photons/maker.photon.d.ts +182 -0
- package/dist/photons/maker.photon.d.ts.map +1 -0
- package/dist/photons/maker.photon.js +504 -0
- package/dist/photons/maker.photon.js.map +1 -0
- package/dist/photons/maker.photon.ts +626 -0
- package/dist/photons/marketplace.photon.d.ts +110 -0
- package/dist/photons/marketplace.photon.d.ts.map +1 -0
- package/dist/photons/marketplace.photon.js +260 -0
- package/dist/photons/marketplace.photon.js.map +1 -0
- package/dist/photons/marketplace.photon.ts +378 -0
- package/dist/photons/tunnel.photon.d.ts +80 -0
- package/dist/photons/tunnel.photon.d.ts.map +1 -0
- package/dist/photons/tunnel.photon.js +269 -0
- package/dist/photons/tunnel.photon.js.map +1 -0
- package/dist/photons/tunnel.photon.ts +345 -0
- package/dist/security-scanner.d.ts.map +1 -1
- package/dist/security-scanner.js +18 -15
- package/dist/security-scanner.js.map +1 -1
- package/dist/serv/auth/jwt.d.ts +89 -0
- package/dist/serv/auth/jwt.d.ts.map +1 -0
- package/dist/serv/auth/jwt.js +239 -0
- package/dist/serv/auth/jwt.js.map +1 -0
- package/dist/serv/auth/oauth.d.ts +117 -0
- package/dist/serv/auth/oauth.d.ts.map +1 -0
- package/dist/serv/auth/oauth.js +395 -0
- package/dist/serv/auth/oauth.js.map +1 -0
- package/dist/serv/auth/well-known.d.ts +60 -0
- package/dist/serv/auth/well-known.d.ts.map +1 -0
- package/dist/serv/auth/well-known.js +154 -0
- package/dist/serv/auth/well-known.js.map +1 -0
- package/dist/serv/db/d1-client.d.ts +65 -0
- package/dist/serv/db/d1-client.d.ts.map +1 -0
- package/dist/serv/db/d1-client.js +137 -0
- package/dist/serv/db/d1-client.js.map +1 -0
- package/dist/serv/db/d1-stores.d.ts +62 -0
- package/dist/serv/db/d1-stores.d.ts.map +1 -0
- package/dist/serv/db/d1-stores.js +307 -0
- package/dist/serv/db/d1-stores.js.map +1 -0
- package/dist/serv/index.d.ts +114 -0
- package/dist/serv/index.d.ts.map +1 -0
- package/dist/serv/index.js +172 -0
- package/dist/serv/index.js.map +1 -0
- package/dist/serv/local.d.ts +118 -0
- package/dist/serv/local.d.ts.map +1 -0
- package/dist/serv/local.js +392 -0
- package/dist/serv/local.js.map +1 -0
- package/dist/serv/middleware/auth.d.ts +66 -0
- package/dist/serv/middleware/auth.d.ts.map +1 -0
- package/dist/serv/middleware/auth.js +178 -0
- package/dist/serv/middleware/auth.js.map +1 -0
- package/dist/serv/middleware/tenant.d.ts +94 -0
- package/dist/serv/middleware/tenant.d.ts.map +1 -0
- package/dist/serv/middleware/tenant.js +152 -0
- package/dist/serv/middleware/tenant.js.map +1 -0
- package/dist/serv/runtime/executor.d.ts +76 -0
- package/dist/serv/runtime/executor.d.ts.map +1 -0
- package/dist/serv/runtime/executor.js +105 -0
- package/dist/serv/runtime/executor.js.map +1 -0
- package/dist/serv/runtime/index.d.ts +8 -0
- package/dist/serv/runtime/index.d.ts.map +1 -0
- package/dist/serv/runtime/index.js +10 -0
- package/dist/serv/runtime/index.js.map +1 -0
- package/dist/serv/runtime/oauth-context.d.ts +121 -0
- package/dist/serv/runtime/oauth-context.d.ts.map +1 -0
- package/dist/serv/runtime/oauth-context.js +153 -0
- package/dist/serv/runtime/oauth-context.js.map +1 -0
- package/dist/serv/session/kv-store.d.ts +54 -0
- package/dist/serv/session/kv-store.d.ts.map +1 -0
- package/dist/serv/session/kv-store.js +149 -0
- package/dist/serv/session/kv-store.js.map +1 -0
- package/dist/serv/session/store.d.ts +113 -0
- package/dist/serv/session/store.d.ts.map +1 -0
- package/dist/serv/session/store.js +284 -0
- package/dist/serv/session/store.js.map +1 -0
- package/dist/serv/types/index.d.ts +147 -0
- package/dist/serv/types/index.d.ts.map +1 -0
- package/dist/serv/types/index.js +8 -0
- package/dist/serv/types/index.js.map +1 -0
- package/dist/serv/vault/token-vault.d.ts +102 -0
- package/dist/serv/vault/token-vault.d.ts.map +1 -0
- package/dist/serv/vault/token-vault.js +177 -0
- package/dist/serv/vault/token-vault.js.map +1 -0
- package/dist/server.d.ts +184 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1995 -86
- package/dist/server.js.map +1 -1
- package/dist/shared/cli-sections.d.ts +6 -0
- package/dist/shared/cli-sections.d.ts.map +1 -0
- package/dist/shared/cli-sections.js +16 -0
- package/dist/shared/cli-sections.js.map +1 -0
- package/dist/shared/cli-utils.d.ts +81 -0
- package/dist/shared/cli-utils.d.ts.map +1 -0
- package/dist/shared/cli-utils.js +174 -0
- package/dist/shared/cli-utils.js.map +1 -0
- package/dist/shared/config-docs.d.ts +6 -0
- package/dist/shared/config-docs.d.ts.map +1 -0
- package/dist/shared/config-docs.js +6 -0
- package/dist/shared/config-docs.js.map +1 -0
- package/dist/shared/error-handler.d.ts +128 -0
- package/dist/shared/error-handler.d.ts.map +1 -0
- package/dist/shared/error-handler.js +342 -0
- package/dist/shared/error-handler.js.map +1 -0
- package/dist/shared/logger.d.ts +42 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +123 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/performance.d.ts +65 -0
- package/dist/shared/performance.d.ts.map +1 -0
- package/dist/shared/performance.js +136 -0
- package/dist/shared/performance.js.map +1 -0
- package/dist/shared/task-runner.d.ts +2 -0
- package/dist/shared/task-runner.d.ts.map +1 -0
- package/dist/shared/task-runner.js +16 -0
- package/dist/shared/task-runner.js.map +1 -0
- package/dist/shared/validation.d.ts +6 -0
- package/dist/shared/validation.d.ts.map +1 -0
- package/dist/shared/validation.js +6 -0
- package/dist/shared/validation.js.map +1 -0
- package/dist/shared-utils.d.ts +63 -0
- package/dist/shared-utils.d.ts.map +1 -0
- package/dist/shared-utils.js +123 -0
- package/dist/shared-utils.js.map +1 -0
- package/dist/template-manager.d.ts +23 -2
- package/dist/template-manager.d.ts.map +1 -1
- package/dist/template-manager.js +176 -87
- package/dist/template-manager.js.map +1 -1
- package/dist/test-client.d.ts.map +1 -1
- package/dist/test-client.js +10 -8
- package/dist/test-client.js.map +1 -1
- package/dist/test-runner.d.ts +52 -0
- package/dist/test-runner.d.ts.map +1 -0
- package/dist/test-runner.js +785 -0
- package/dist/test-runner.js.map +1 -0
- package/dist/testing.d.ts +103 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +163 -0
- package/dist/testing.js.map +1 -0
- package/dist/version-checker.d.ts.map +1 -1
- package/dist/version-checker.js +2 -2
- package/dist/version-checker.js.map +1 -1
- package/dist/version.d.ts +10 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +21 -0
- package/dist/version.js.map +1 -0
- package/dist/watcher.d.ts +6 -3
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +49 -10
- package/dist/watcher.js.map +1 -1
- package/package.json +57 -7
- package/templates/cloudflare/worker.ts.template +381 -0
- package/templates/cloudflare/wrangler.toml.template +9 -0
- package/dist/base.d.ts +0 -58
- package/dist/base.d.ts.map +0 -1
- package/dist/base.js +0 -92
- package/dist/base.js.map +0 -1
- package/dist/dependency-manager.d.ts +0 -49
- package/dist/dependency-manager.d.ts.map +0 -1
- package/dist/dependency-manager.js +0 -165
- package/dist/dependency-manager.js.map +0 -1
- package/dist/registry-manager.d.ts +0 -76
- package/dist/registry-manager.d.ts.map +0 -1
- package/dist/registry-manager.js +0 -220
- package/dist/registry-manager.js.map +0 -1
- package/dist/schema-extractor.d.ts +0 -110
- package/dist/schema-extractor.d.ts.map +0 -1
- package/dist/schema-extractor.js +0 -727
- package/dist/schema-extractor.js.map +0 -1
- package/dist/test-marketplace-sources.d.ts +0 -5
- package/dist/test-marketplace-sources.d.ts.map +0 -1
- package/dist/test-marketplace-sources.js +0 -53
- package/dist/test-marketplace-sources.js.map +0 -1
- package/dist/types.d.ts +0 -109
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -12
- package/dist/types.js.map +0 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
2
3
|
import { SchemaExtractor } from '@portel/photon-core';
|
|
4
|
+
import { PHOTON_VERSION } from './version.js';
|
|
3
5
|
/**
|
|
4
6
|
* Extracts comprehensive documentation from Photon files
|
|
5
7
|
*
|
|
@@ -22,20 +24,35 @@ export class PhotonDocExtractor {
|
|
|
22
24
|
this.content = await fs.readFile(this.filePath, 'utf-8');
|
|
23
25
|
const statefulTag = this.extractTag('stateful');
|
|
24
26
|
const idleTimeoutTag = this.extractTag('idleTimeout');
|
|
27
|
+
const internalTag = this.extractTag('internal');
|
|
28
|
+
const tools = await this.extractTools();
|
|
29
|
+
const photonType = this.detectPhotonType(tools);
|
|
30
|
+
const features = this.detectFeatures(tools, statefulTag !== undefined);
|
|
31
|
+
const externalDeps = this.extractDependencies();
|
|
32
|
+
const diagram = this.generateDiagramSync(tools, photonType, externalDeps);
|
|
25
33
|
return {
|
|
26
34
|
name: this.extractName(),
|
|
27
|
-
|
|
35
|
+
label: this.extractTag('label'),
|
|
36
|
+
version: this.extractTag('version') || PHOTON_VERSION,
|
|
28
37
|
description: this.extractDescription(),
|
|
29
38
|
author: this.extractTag('author'),
|
|
30
39
|
license: this.extractTag('license'),
|
|
31
40
|
repository: this.extractTag('repository'),
|
|
32
41
|
homepage: this.extractTag('homepage'),
|
|
42
|
+
icon: this.extractTag('icon'),
|
|
43
|
+
internal: internalTag !== undefined,
|
|
33
44
|
configParams: this.extractConfigParams(),
|
|
34
45
|
setupInstructions: this.extractSetupInstructions(),
|
|
35
|
-
tools
|
|
46
|
+
tools,
|
|
36
47
|
dependencies: this.extractTag('dependencies'),
|
|
37
|
-
|
|
48
|
+
runtime: this.extractTag('runtime'),
|
|
49
|
+
stateful: statefulTag !== undefined,
|
|
38
50
|
idleTimeout: idleTimeoutTag ? parseInt(idleTimeoutTag, 10) : undefined,
|
|
51
|
+
assets: await this.extractAssets(),
|
|
52
|
+
photonType,
|
|
53
|
+
features,
|
|
54
|
+
externalDeps,
|
|
55
|
+
diagram,
|
|
39
56
|
};
|
|
40
57
|
}
|
|
41
58
|
/**
|
|
@@ -62,9 +79,18 @@ export class PhotonDocExtractor {
|
|
|
62
79
|
* Extract a specific JSDoc tag value
|
|
63
80
|
*/
|
|
64
81
|
extractTag(tagName) {
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
82
|
+
// First try to match tag with value: @tagName value
|
|
83
|
+
const regexWithValue = new RegExp(`@${tagName}\\s+(.+?)(?=\\n|$)`, 'm');
|
|
84
|
+
const matchWithValue = this.content.match(regexWithValue);
|
|
85
|
+
if (matchWithValue) {
|
|
86
|
+
return matchWithValue[1].trim();
|
|
87
|
+
}
|
|
88
|
+
// Then check for boolean tag without value: @tagName (followed by newline, *, or end)
|
|
89
|
+
const regexBoolean = new RegExp(`@${tagName}(?:\\s*\\n|\\s*\\*|$)`, 'm');
|
|
90
|
+
if (this.content.match(regexBoolean)) {
|
|
91
|
+
return 'true'; // Presence of tag means true
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
68
94
|
}
|
|
69
95
|
/**
|
|
70
96
|
* Extract configuration parameters from constructor
|
|
@@ -80,7 +106,10 @@ export class PhotonDocExtractor {
|
|
|
80
106
|
return params.map((param) => {
|
|
81
107
|
// Convert to environment variable format
|
|
82
108
|
// ClassName -> class-name -> CLASS_NAME_PARAM_NAME
|
|
83
|
-
const kebabCase = className
|
|
109
|
+
const kebabCase = className
|
|
110
|
+
.replace(/([A-Z])/g, '-$1')
|
|
111
|
+
.toLowerCase()
|
|
112
|
+
.replace(/^-/, '');
|
|
84
113
|
const envPrefix = kebabCase.toUpperCase().replace(/-/g, '_');
|
|
85
114
|
const envVar = `${envPrefix}_${param.name.toUpperCase()}`;
|
|
86
115
|
// Find description from Configuration section
|
|
@@ -138,24 +167,79 @@ export class PhotonDocExtractor {
|
|
|
138
167
|
// Clean up the configuration text
|
|
139
168
|
return configMatch[1]
|
|
140
169
|
.split('\n')
|
|
141
|
-
.map(line => line.replace(/^\s*\*\s?/, '').trim())
|
|
142
|
-
.filter(line => line.length > 0)
|
|
170
|
+
.map((line) => line.replace(/^\s*\*\s?/, '').trim())
|
|
171
|
+
.filter((line) => line.length > 0)
|
|
143
172
|
.join('\n')
|
|
144
173
|
.trim();
|
|
145
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Extract assets associated with the Photon
|
|
177
|
+
* Scans for ui/, prompts/, resources/ folders and @ui annotations
|
|
178
|
+
*/
|
|
179
|
+
async extractAssets() {
|
|
180
|
+
const assets = new Set();
|
|
181
|
+
const dir = path.dirname(this.filePath);
|
|
182
|
+
const basename = path.basename(this.filePath, '.photon.ts');
|
|
183
|
+
// Convention: asset folder has same name as photon (without .photon.ts)
|
|
184
|
+
// e.g. test-ui.photon.ts -> test-ui/
|
|
185
|
+
const assetFolder = path.join(dir, basename);
|
|
186
|
+
// Check if asset folder exists
|
|
187
|
+
try {
|
|
188
|
+
const stats = await fs.stat(assetFolder);
|
|
189
|
+
if (stats.isDirectory()) {
|
|
190
|
+
// Recursively find all files in the asset folder
|
|
191
|
+
const findFiles = async (currentDir, relativePath) => {
|
|
192
|
+
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
193
|
+
for (const entry of entries) {
|
|
194
|
+
const entryPath = path.join(currentDir, entry.name);
|
|
195
|
+
const entryRelative = path.join(relativePath, entry.name);
|
|
196
|
+
if (entry.isDirectory()) {
|
|
197
|
+
await findFiles(entryPath, entryRelative);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
// Add relative path from photon file's directory
|
|
201
|
+
// e.g. test-ui/ui/index.html
|
|
202
|
+
assets.add(path.join(basename, entryRelative));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
await findFiles(assetFolder, '');
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Asset folder doesn't exist, ignore
|
|
211
|
+
}
|
|
212
|
+
// Extract explicit @ui assets from JSDoc
|
|
213
|
+
// Format: @ui <id> <path>
|
|
214
|
+
const uiRegex = /@ui[ \t]+\S+[ \t]+(\S+)/g;
|
|
215
|
+
let match;
|
|
216
|
+
while ((match = uiRegex.exec(this.content)) !== null) {
|
|
217
|
+
const assetPath = match[1];
|
|
218
|
+
// Only include relative paths
|
|
219
|
+
if (assetPath.startsWith('./') || !path.isAbsolute(assetPath)) {
|
|
220
|
+
// Normalize path
|
|
221
|
+
const normalized = assetPath.startsWith('./') ? assetPath.slice(2) : assetPath;
|
|
222
|
+
assets.add(normalized);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return Array.from(assets);
|
|
226
|
+
}
|
|
146
227
|
/**
|
|
147
228
|
* Extract tool methods with their documentation
|
|
148
229
|
*/
|
|
149
230
|
async extractTools() {
|
|
150
231
|
const tools = [];
|
|
151
|
-
//
|
|
152
|
-
const methodRegex = /async\s+(\w+)\s*\([^)]
|
|
232
|
+
// Find all async methods (including generators with async *)
|
|
233
|
+
const methodRegex = /async\s+(\*?)\s*(\w+)\s*\(([^)]*)\)/g;
|
|
153
234
|
let match;
|
|
154
235
|
while ((match = methodRegex.exec(this.content)) !== null) {
|
|
155
|
-
const
|
|
236
|
+
const isGenerator = match[1] === '*';
|
|
237
|
+
const methodName = match[2];
|
|
238
|
+
const methodSignatureParams = match[3] || '';
|
|
156
239
|
const methodIndex = match.index;
|
|
157
|
-
// Skip private methods (starting with _) and
|
|
240
|
+
// Skip private methods (starting with _), lifecycle methods, and test methods
|
|
158
241
|
if (methodName.startsWith('_') ||
|
|
242
|
+
methodName.startsWith('test') ||
|
|
159
243
|
methodName === 'onInitialize' ||
|
|
160
244
|
methodName === 'onShutdown') {
|
|
161
245
|
continue;
|
|
@@ -175,8 +259,9 @@ export class PhotonDocExtractor {
|
|
|
175
259
|
continue; // Skip if JSDoc is malformed
|
|
176
260
|
}
|
|
177
261
|
const jsdoc = jsdocMatch[1];
|
|
178
|
-
const tool = this.parseToolMethodFromJSDoc(jsdoc, methodName);
|
|
262
|
+
const tool = this.parseToolMethodFromJSDoc(jsdoc, methodName, methodSignatureParams);
|
|
179
263
|
if (tool) {
|
|
264
|
+
tool.isGenerator = isGenerator;
|
|
180
265
|
tools.push(tool);
|
|
181
266
|
}
|
|
182
267
|
}
|
|
@@ -215,24 +300,50 @@ export class PhotonDocExtractor {
|
|
|
215
300
|
constraints.push(`pattern: ${patternMatch[1]}`);
|
|
216
301
|
cleanDesc = cleanDesc.replace(/\{@pattern\s+[^}]+\}\s*/g, '');
|
|
217
302
|
}
|
|
218
|
-
// Extract {@
|
|
303
|
+
// Extract {@choice value1,value2,...}
|
|
304
|
+
const choiceMatch = cleanDesc.match(/\{@choice\s+([^}]+)\}/);
|
|
305
|
+
if (choiceMatch) {
|
|
306
|
+
constraints.push(`choice: ${choiceMatch[1]}`);
|
|
307
|
+
cleanDesc = cleanDesc.replace(/\{@choice\s+[^}]+\}\s*/g, '');
|
|
308
|
+
}
|
|
309
|
+
// Extract {@field type}
|
|
310
|
+
const fieldMatch = cleanDesc.match(/\{@field\s+([a-z]+)\}/);
|
|
311
|
+
if (fieldMatch) {
|
|
312
|
+
constraints.push(`field: ${fieldMatch[1]}`);
|
|
313
|
+
cleanDesc = cleanDesc.replace(/\{@field\s+[a-z]+\}\s*/g, '');
|
|
314
|
+
}
|
|
315
|
+
// Extract {@example value} - handle nested braces and brackets in JSON examples
|
|
219
316
|
const exampleStart = cleanDesc.indexOf('{@example ');
|
|
220
317
|
if (exampleStart !== -1) {
|
|
221
318
|
const contentStart = exampleStart + '{@example '.length;
|
|
222
|
-
let
|
|
319
|
+
let braceDepth = 0;
|
|
320
|
+
let bracketDepth = 0;
|
|
223
321
|
let i = contentStart;
|
|
224
|
-
|
|
322
|
+
let inString = false;
|
|
323
|
+
// Find the closing } by counting braces and brackets, respecting strings
|
|
225
324
|
while (i < cleanDesc.length) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
325
|
+
const ch = cleanDesc[i];
|
|
326
|
+
const prevCh = i > 0 ? cleanDesc[i - 1] : '';
|
|
327
|
+
// Handle string boundaries (skip escaped quotes)
|
|
328
|
+
if (ch === '"' && prevCh !== '\\') {
|
|
329
|
+
inString = !inString;
|
|
330
|
+
}
|
|
331
|
+
else if (!inString) {
|
|
332
|
+
if (ch === '{')
|
|
333
|
+
braceDepth++;
|
|
334
|
+
else if (ch === '[')
|
|
335
|
+
bracketDepth++;
|
|
336
|
+
else if (ch === ']')
|
|
337
|
+
bracketDepth--;
|
|
338
|
+
else if (ch === '}') {
|
|
339
|
+
if (braceDepth === 0 && bracketDepth === 0) {
|
|
340
|
+
// Found the closing brace of the {@example} tag
|
|
341
|
+
example = cleanDesc.substring(contentStart, i).trim();
|
|
342
|
+
cleanDesc = cleanDesc.substring(0, exampleStart) + cleanDesc.substring(i + 1);
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
braceDepth--;
|
|
234
346
|
}
|
|
235
|
-
depth--;
|
|
236
347
|
}
|
|
237
348
|
i++;
|
|
238
349
|
}
|
|
@@ -248,16 +359,30 @@ export class PhotonDocExtractor {
|
|
|
248
359
|
/**
|
|
249
360
|
* Parse a single tool method from its JSDoc content
|
|
250
361
|
*/
|
|
251
|
-
parseToolMethodFromJSDoc(jsdoc, methodName) {
|
|
362
|
+
parseToolMethodFromJSDoc(jsdoc, methodName, signatureParams) {
|
|
252
363
|
// Extract method description (first line(s) before @param)
|
|
253
364
|
const descMatch = jsdoc.match(/^\s*\*\s*(.+?)(?=\n\s*\*\s*@|\n\s*$)/s);
|
|
254
365
|
const description = descMatch
|
|
255
366
|
? descMatch[1]
|
|
256
367
|
.split('\n')
|
|
257
|
-
.map(line => line.replace(/^\s*\*\s?/, '').trim())
|
|
368
|
+
.map((line) => line.replace(/^\s*\*\s?/, '').trim())
|
|
258
369
|
.join(' ')
|
|
259
370
|
.trim()
|
|
260
371
|
: '';
|
|
372
|
+
// Extract type map from method signature (e.g. "path: string, recursive?: boolean")
|
|
373
|
+
const sigTypes = {};
|
|
374
|
+
if (signatureParams) {
|
|
375
|
+
// Handle both flat params (name: string) and object params (params: { name: string; encoding?: string })
|
|
376
|
+
const objectMatch = signatureParams.match(/^\s*\w+\s*:\s*\{([^}]+)\}/);
|
|
377
|
+
const sigContent = objectMatch ? objectMatch[1] : signatureParams;
|
|
378
|
+
// Split on both commas and semicolons (TS object types use semicolons)
|
|
379
|
+
for (const part of sigContent.split(/[,;]/)) {
|
|
380
|
+
const m = part.trim().match(/^(\w+)(\?)?:\s*(.+)$/);
|
|
381
|
+
if (m) {
|
|
382
|
+
sigTypes[m[1]] = { type: m[3].trim(), optional: !!m[2] };
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
261
386
|
// Extract parameters from JSDoc @param tags
|
|
262
387
|
const params = [];
|
|
263
388
|
const paramRegex = /@param\s+(\w+)\s+(.+?)(?=\n\s*\*\s*@|\n\s*\*\/|\n\s*$)/gs;
|
|
@@ -270,11 +395,16 @@ export class PhotonDocExtractor {
|
|
|
270
395
|
// Try to extract type and optional info from description
|
|
271
396
|
// Format: "Param description (optional)" or "Param description (default: value)"
|
|
272
397
|
let cleanDesc = parsed.description;
|
|
273
|
-
const optional = /\(optional\)/i.test(cleanDesc) || /\(default:/i.test(cleanDesc);
|
|
274
|
-
cleanDesc = cleanDesc
|
|
398
|
+
const optional = /\(optional\)/i.test(cleanDesc) || /\(default:/i.test(cleanDesc) || (sigTypes[paramName]?.optional ?? false);
|
|
399
|
+
cleanDesc = cleanDesc
|
|
400
|
+
.replace(/\(optional\)/gi, '')
|
|
401
|
+
.replace(/\(default:.*?\)/gi, '')
|
|
402
|
+
.trim();
|
|
403
|
+
// Use type from method signature if available, fall back to 'any'
|
|
404
|
+
const paramType = sigTypes[paramName]?.type || 'any';
|
|
275
405
|
params.push({
|
|
276
406
|
name: paramName,
|
|
277
|
-
type:
|
|
407
|
+
type: paramType,
|
|
278
408
|
optional,
|
|
279
409
|
description: cleanDesc,
|
|
280
410
|
constraintsFormatted: parsed.constraintsFormatted,
|
|
@@ -288,7 +418,7 @@ export class PhotonDocExtractor {
|
|
|
288
418
|
if (exampleMatch) {
|
|
289
419
|
const exampleText = exampleMatch[1]
|
|
290
420
|
.split('\n')
|
|
291
|
-
.map(line => line.replace(/^\s*\*\s?/, ''))
|
|
421
|
+
.map((line) => line.replace(/^\s*\*\s?/, ''))
|
|
292
422
|
.join('\n')
|
|
293
423
|
.trim();
|
|
294
424
|
// Only use it if it looks like actual code (not just a simple value from inline tag)
|
|
@@ -304,5 +434,403 @@ export class PhotonDocExtractor {
|
|
|
304
434
|
example,
|
|
305
435
|
};
|
|
306
436
|
}
|
|
437
|
+
// ============================================
|
|
438
|
+
// FEATURE DETECTION
|
|
439
|
+
// ============================================
|
|
440
|
+
/**
|
|
441
|
+
* Detect platform features used by this Photon
|
|
442
|
+
*/
|
|
443
|
+
detectFeatures(tools, isStateful) {
|
|
444
|
+
const features = [];
|
|
445
|
+
// generator — any async * method
|
|
446
|
+
if (tools.some((t) => t.isGenerator)) {
|
|
447
|
+
features.push('generator');
|
|
448
|
+
}
|
|
449
|
+
// custom-ui — @ui JSDoc tag
|
|
450
|
+
if (this.extractTag('ui') !== undefined || /@ui\s+\S+/.test(this.content)) {
|
|
451
|
+
features.push('custom-ui');
|
|
452
|
+
}
|
|
453
|
+
// elicitation — yield { ask: patterns
|
|
454
|
+
if (/yield\s*\{\s*ask\s*:/.test(this.content) || /yield\*\s/.test(this.content)) {
|
|
455
|
+
features.push('elicitation');
|
|
456
|
+
}
|
|
457
|
+
// streaming — yield { emit: or yield { step:
|
|
458
|
+
if (/yield\s*\{\s*(emit|step)\s*:/.test(this.content)) {
|
|
459
|
+
features.push('streaming');
|
|
460
|
+
}
|
|
461
|
+
// oauth — yield { ask: 'oauth'
|
|
462
|
+
if (/yield\s*\{\s*ask\s*:\s*['"]oauth['"]/.test(this.content)) {
|
|
463
|
+
features.push('oauth');
|
|
464
|
+
}
|
|
465
|
+
// stateful — @stateful tag
|
|
466
|
+
if (isStateful) {
|
|
467
|
+
features.push('stateful');
|
|
468
|
+
}
|
|
469
|
+
// webhooks — webhook endpoint patterns
|
|
470
|
+
if (/webhook/i.test(this.content) && /@webhook/.test(this.content)) {
|
|
471
|
+
features.push('webhooks');
|
|
472
|
+
}
|
|
473
|
+
// channels — channel in emit patterns
|
|
474
|
+
if (/channel/i.test(this.content) && /emit/.test(this.content)) {
|
|
475
|
+
features.push('channels');
|
|
476
|
+
}
|
|
477
|
+
// locks — acquireLock / releaseLock
|
|
478
|
+
if (/acquireLock|releaseLock/.test(this.content)) {
|
|
479
|
+
features.push('locks');
|
|
480
|
+
}
|
|
481
|
+
// mcp-bridge — this.mcp( calls
|
|
482
|
+
if (/this\.mcp\(/.test(this.content)) {
|
|
483
|
+
features.push('mcp-bridge');
|
|
484
|
+
}
|
|
485
|
+
// photon-bridge — this.photon( calls
|
|
486
|
+
if (/this\.photon\(/.test(this.content)) {
|
|
487
|
+
features.push('photon-bridge');
|
|
488
|
+
}
|
|
489
|
+
// wizard — @wizard tag
|
|
490
|
+
if (this.extractTag('wizard') !== undefined) {
|
|
491
|
+
features.push('wizard');
|
|
492
|
+
}
|
|
493
|
+
// dashboard — @ui + main method with linkedUi pattern
|
|
494
|
+
if (features.includes('custom-ui') &&
|
|
495
|
+
/async\s+\*?\s*main\b/.test(this.content) &&
|
|
496
|
+
/linkedUi|dashboard/i.test(this.content)) {
|
|
497
|
+
features.push('dashboard');
|
|
498
|
+
}
|
|
499
|
+
return features;
|
|
500
|
+
}
|
|
501
|
+
// ============================================
|
|
502
|
+
// DIAGRAM GENERATION
|
|
503
|
+
// ============================================
|
|
504
|
+
/**
|
|
505
|
+
* Generate a Mermaid diagram for this Photon
|
|
506
|
+
* Automatically detects the Photon type and generates appropriate diagram
|
|
507
|
+
*/
|
|
508
|
+
async generateDiagram() {
|
|
509
|
+
if (!this.content) {
|
|
510
|
+
this.content = await fs.readFile(this.filePath, 'utf-8');
|
|
511
|
+
}
|
|
512
|
+
const tools = await this.extractTools();
|
|
513
|
+
const photonType = this.detectPhotonType(tools);
|
|
514
|
+
const name = this.extractName();
|
|
515
|
+
const deps = this.extractDependencies();
|
|
516
|
+
switch (photonType) {
|
|
517
|
+
case 'workflow':
|
|
518
|
+
return this.generateWorkflowDiagram(name, tools, deps);
|
|
519
|
+
case 'streaming':
|
|
520
|
+
return this.generateStreamingDiagram(name, tools, deps);
|
|
521
|
+
default:
|
|
522
|
+
return this.generateApiSurfaceDiagram(name, tools, deps);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Generate diagram synchronously when content and tools are already loaded
|
|
527
|
+
*/
|
|
528
|
+
generateDiagramSync(tools, photonType, deps) {
|
|
529
|
+
const name = this.extractName();
|
|
530
|
+
switch (photonType) {
|
|
531
|
+
case 'workflow':
|
|
532
|
+
return this.generateWorkflowDiagram(name, tools, deps);
|
|
533
|
+
case 'streaming':
|
|
534
|
+
return this.generateStreamingDiagram(name, tools, deps);
|
|
535
|
+
default:
|
|
536
|
+
return this.generateApiSurfaceDiagram(name, tools, deps);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Detect the type of Photon based on its methods
|
|
541
|
+
*/
|
|
542
|
+
detectPhotonType(tools) {
|
|
543
|
+
const hasGenerator = tools.some((t) => t.isGenerator);
|
|
544
|
+
const hasAskEmit = this.hasAskEmitPatterns();
|
|
545
|
+
if (hasGenerator && hasAskEmit)
|
|
546
|
+
return 'workflow';
|
|
547
|
+
if (hasGenerator)
|
|
548
|
+
return 'streaming';
|
|
549
|
+
return 'api';
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Check if content has ask/emit yield patterns
|
|
553
|
+
*/
|
|
554
|
+
hasAskEmitPatterns() {
|
|
555
|
+
return /yield\s*\{\s*(ask|emit)\s*:/.test(this.content);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Extract dependencies from JSDoc tags
|
|
559
|
+
*/
|
|
560
|
+
extractDependencies() {
|
|
561
|
+
const mcpsTag = this.extractTag('mcps');
|
|
562
|
+
const photonsTag = this.extractTag('photons');
|
|
563
|
+
const depsTag = this.extractTag('dependencies');
|
|
564
|
+
return {
|
|
565
|
+
mcps: mcpsTag ? mcpsTag.split(/[,\s]+/).filter(Boolean) : [],
|
|
566
|
+
photons: photonsTag ? photonsTag.split(/[,\s]+/).filter(Boolean) : [],
|
|
567
|
+
npm: depsTag
|
|
568
|
+
? depsTag
|
|
569
|
+
.split(/[,\s]+/)
|
|
570
|
+
.map((d) => d.split('@')[0])
|
|
571
|
+
.filter(Boolean)
|
|
572
|
+
: [],
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Extract yield statements from content
|
|
577
|
+
*/
|
|
578
|
+
extractYieldStatements() {
|
|
579
|
+
const yields = [];
|
|
580
|
+
// Match: const varName = yield { ask: 'type', message: '...' }
|
|
581
|
+
// or: yield { emit: 'type', message: '...' }
|
|
582
|
+
const yieldRegex = /(?:const\s+(\w+)\s*(?::\s*\w+)?\s*=\s*)?yield\s*\{\s*(ask|emit)\s*:\s*['"](\w+)['"]\s*(?:,\s*message\s*:\s*[`'"]([^`'"]*)[`'"])?/g;
|
|
583
|
+
let match;
|
|
584
|
+
while ((match = yieldRegex.exec(this.content)) !== null) {
|
|
585
|
+
yields.push({
|
|
586
|
+
variable: match[1],
|
|
587
|
+
type: match[2],
|
|
588
|
+
subtype: match[3],
|
|
589
|
+
message: match[4],
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
return yields;
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Extract MCP and Photon calls from content
|
|
596
|
+
*/
|
|
597
|
+
extractExternalCalls() {
|
|
598
|
+
const calls = [];
|
|
599
|
+
// Match: this.mcp('name').method() or await this.mcp('name').method()
|
|
600
|
+
const mcpRegex = /this\.mcp\(['"](\w+)['"]\)\.(\w+)/g;
|
|
601
|
+
let match;
|
|
602
|
+
while ((match = mcpRegex.exec(this.content)) !== null) {
|
|
603
|
+
calls.push({ type: 'mcp', name: match[1], method: match[2] });
|
|
604
|
+
}
|
|
605
|
+
// Match: this.photon('name').method() or yield* this.photon('name').method()
|
|
606
|
+
const photonRegex = /this\.photon\(['"](\w+)['"]\)\.(\w+)/g;
|
|
607
|
+
while ((match = photonRegex.exec(this.content)) !== null) {
|
|
608
|
+
calls.push({ type: 'photon', name: match[1], method: match[2] });
|
|
609
|
+
}
|
|
610
|
+
return calls;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Infer emoji based on method/tool name
|
|
614
|
+
*/
|
|
615
|
+
inferEmoji(name) {
|
|
616
|
+
const lower = name.toLowerCase();
|
|
617
|
+
if (/^(read|get|fetch|load|find|query|search|list)/.test(lower))
|
|
618
|
+
return '📖';
|
|
619
|
+
if (/^(write|create|save|put|add|insert|set)/.test(lower))
|
|
620
|
+
return '✏️';
|
|
621
|
+
if (/^(delete|remove|drop|clear)/.test(lower))
|
|
622
|
+
return '🗑️';
|
|
623
|
+
if (/^(send|post|push|publish|notify)/.test(lower))
|
|
624
|
+
return '📤';
|
|
625
|
+
if (/^(update|modify|patch|edit)/.test(lower))
|
|
626
|
+
return '🔄';
|
|
627
|
+
if (/^(validate|check|verify|test)/.test(lower))
|
|
628
|
+
return '✅';
|
|
629
|
+
if (/^(config|setup|init)/.test(lower))
|
|
630
|
+
return '⚙️';
|
|
631
|
+
if (/^(run|execute|start|begin)/.test(lower))
|
|
632
|
+
return '▶️';
|
|
633
|
+
if (/^(stop|cancel|abort|end)/.test(lower))
|
|
634
|
+
return '⏹️';
|
|
635
|
+
if (/^(connect|login|auth)/.test(lower))
|
|
636
|
+
return '🔌';
|
|
637
|
+
if (/^(download|export)/.test(lower))
|
|
638
|
+
return '📥';
|
|
639
|
+
if (/^(upload|import)/.test(lower))
|
|
640
|
+
return '📤';
|
|
641
|
+
return '🔧';
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Get emoji for ask type
|
|
645
|
+
*/
|
|
646
|
+
getAskEmoji(subtype) {
|
|
647
|
+
switch (subtype) {
|
|
648
|
+
case 'confirm':
|
|
649
|
+
return '🙋';
|
|
650
|
+
case 'select':
|
|
651
|
+
return '📋';
|
|
652
|
+
case 'text':
|
|
653
|
+
return '✏️';
|
|
654
|
+
case 'number':
|
|
655
|
+
return '🔢';
|
|
656
|
+
case 'password':
|
|
657
|
+
return '🔒';
|
|
658
|
+
case 'date':
|
|
659
|
+
return '📅';
|
|
660
|
+
case 'file':
|
|
661
|
+
return '📁';
|
|
662
|
+
default:
|
|
663
|
+
return '❓';
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Get emoji for emit type
|
|
668
|
+
*/
|
|
669
|
+
getEmitEmoji(subtype) {
|
|
670
|
+
switch (subtype) {
|
|
671
|
+
case 'status':
|
|
672
|
+
return '📢';
|
|
673
|
+
case 'progress':
|
|
674
|
+
return '⏳';
|
|
675
|
+
case 'log':
|
|
676
|
+
return '📝';
|
|
677
|
+
case 'toast':
|
|
678
|
+
return '🎉';
|
|
679
|
+
case 'thinking':
|
|
680
|
+
return '🧠';
|
|
681
|
+
case 'artifact':
|
|
682
|
+
return '📊';
|
|
683
|
+
case 'stream':
|
|
684
|
+
return '💬';
|
|
685
|
+
default:
|
|
686
|
+
return '📣';
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* Generate API surface diagram for tool collection Photons
|
|
691
|
+
*/
|
|
692
|
+
generateApiSurfaceDiagram(name, tools, deps) {
|
|
693
|
+
const lines = ['flowchart LR'];
|
|
694
|
+
// Main photon subgraph
|
|
695
|
+
lines.push(` subgraph ${this.sanitizeId(name)}["📦 ${this.titleCase(name)}"]`);
|
|
696
|
+
lines.push(' direction TB');
|
|
697
|
+
lines.push(' PHOTON((🎯))');
|
|
698
|
+
tools.forEach((tool, i) => {
|
|
699
|
+
const emoji = this.inferEmoji(tool.name);
|
|
700
|
+
const id = `T${i}`;
|
|
701
|
+
lines.push(` ${id}[${emoji} ${tool.name}]`);
|
|
702
|
+
lines.push(` PHOTON --> ${id}`);
|
|
703
|
+
});
|
|
704
|
+
lines.push(' end');
|
|
705
|
+
// Dependencies subgraph (if any)
|
|
706
|
+
const hasDeps = deps.mcps.length > 0 || deps.photons.length > 0 || deps.npm.length > 0;
|
|
707
|
+
if (hasDeps) {
|
|
708
|
+
lines.push('');
|
|
709
|
+
lines.push(' subgraph deps["Dependencies"]');
|
|
710
|
+
lines.push(' direction TB');
|
|
711
|
+
deps.mcps.forEach((mcp, i) => {
|
|
712
|
+
lines.push(` MCP${i}[🔌 ${mcp}]`);
|
|
713
|
+
});
|
|
714
|
+
deps.photons.forEach((photon, i) => {
|
|
715
|
+
lines.push(` PHO${i}[📦 ${photon}]`);
|
|
716
|
+
});
|
|
717
|
+
deps.npm.forEach((pkg, i) => {
|
|
718
|
+
lines.push(` NPM${i}[📚 ${pkg}]`);
|
|
719
|
+
});
|
|
720
|
+
lines.push(' end');
|
|
721
|
+
}
|
|
722
|
+
return lines.join('\n');
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Generate streaming diagram for generator Photons without ask/emit
|
|
726
|
+
*/
|
|
727
|
+
generateStreamingDiagram(name, tools, deps) {
|
|
728
|
+
// For streaming, show tools with streaming indicator
|
|
729
|
+
const lines = ['flowchart LR'];
|
|
730
|
+
lines.push(` subgraph ${this.sanitizeId(name)}["📦 ${this.titleCase(name)}"]`);
|
|
731
|
+
lines.push(' direction TB');
|
|
732
|
+
lines.push(' PHOTON((🎯))');
|
|
733
|
+
tools.forEach((tool, i) => {
|
|
734
|
+
const emoji = tool.isGenerator ? '🌊' : this.inferEmoji(tool.name);
|
|
735
|
+
const id = `T${i}`;
|
|
736
|
+
const suffix = tool.isGenerator ? ' (stream)' : '';
|
|
737
|
+
lines.push(` ${id}[${emoji} ${tool.name}${suffix}]`);
|
|
738
|
+
lines.push(` PHOTON --> ${id}`);
|
|
739
|
+
});
|
|
740
|
+
lines.push(' end');
|
|
741
|
+
return lines.join('\n');
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Generate workflow flowchart for Photons with ask/emit patterns
|
|
745
|
+
*/
|
|
746
|
+
generateWorkflowDiagram(name, tools, deps) {
|
|
747
|
+
const yields = this.extractYieldStatements();
|
|
748
|
+
const externalCalls = this.extractExternalCalls();
|
|
749
|
+
const lines = ['flowchart TD'];
|
|
750
|
+
lines.push(` subgraph ${this.sanitizeId(name)}["📦 ${this.titleCase(name)}"]`);
|
|
751
|
+
lines.push(' START([▶ Start])');
|
|
752
|
+
let prevNode = 'START';
|
|
753
|
+
let nodeCounter = 0;
|
|
754
|
+
// Process yields and calls in order they appear
|
|
755
|
+
for (const y of yields) {
|
|
756
|
+
const nodeId = `N${nodeCounter++}`;
|
|
757
|
+
if (y.type === 'emit') {
|
|
758
|
+
const emoji = this.getEmitEmoji(y.subtype);
|
|
759
|
+
const msg = y.message ? this.truncate(y.message, 30) : y.subtype;
|
|
760
|
+
lines.push(` ${nodeId}[${emoji} ${msg}]`);
|
|
761
|
+
lines.push(` ${prevNode} --> ${nodeId}`);
|
|
762
|
+
prevNode = nodeId;
|
|
763
|
+
}
|
|
764
|
+
else if (y.type === 'ask') {
|
|
765
|
+
const emoji = this.getAskEmoji(y.subtype);
|
|
766
|
+
const msg = y.message ? this.truncate(y.message, 25) : y.subtype;
|
|
767
|
+
lines.push(` ${nodeId}{${emoji} ${msg}}`);
|
|
768
|
+
lines.push(` ${prevNode} --> ${nodeId}`);
|
|
769
|
+
// For confirm, add Yes/No branches
|
|
770
|
+
if (y.subtype === 'confirm') {
|
|
771
|
+
const cancelId = `N${nodeCounter++}`;
|
|
772
|
+
const continueId = `N${nodeCounter++}`;
|
|
773
|
+
lines.push(` ${cancelId}([❌ Cancelled])`);
|
|
774
|
+
lines.push(` ${nodeId} -->|No| ${cancelId}`);
|
|
775
|
+
lines.push(` ${nodeId} -->|Yes| ${continueId}`);
|
|
776
|
+
// Create a dummy continue node for the flow
|
|
777
|
+
lines.push(` ${continueId}[Continue]`);
|
|
778
|
+
prevNode = continueId;
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
prevNode = nodeId;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
// Add external calls
|
|
786
|
+
for (const call of externalCalls) {
|
|
787
|
+
const nodeId = `N${nodeCounter++}`;
|
|
788
|
+
const emoji = call.type === 'mcp' ? '🔌' : '📦';
|
|
789
|
+
lines.push(` ${nodeId}[${emoji} ${call.name}.${call.method}]`);
|
|
790
|
+
lines.push(` ${prevNode} --> ${nodeId}`);
|
|
791
|
+
prevNode = nodeId;
|
|
792
|
+
}
|
|
793
|
+
// End node
|
|
794
|
+
lines.push(` SUCCESS([✅ Success])`);
|
|
795
|
+
lines.push(` ${prevNode} --> SUCCESS`);
|
|
796
|
+
lines.push(' end');
|
|
797
|
+
// Dependencies
|
|
798
|
+
const hasDeps = deps.mcps.length > 0 || deps.photons.length > 0;
|
|
799
|
+
if (hasDeps) {
|
|
800
|
+
lines.push('');
|
|
801
|
+
lines.push(' subgraph deps["Dependencies"]');
|
|
802
|
+
deps.mcps.forEach((mcp, i) => {
|
|
803
|
+
lines.push(` DEP_MCP${i}[🔌 ${mcp}]`);
|
|
804
|
+
});
|
|
805
|
+
deps.photons.forEach((photon, i) => {
|
|
806
|
+
lines.push(` DEP_PHO${i}[📦 ${photon}]`);
|
|
807
|
+
});
|
|
808
|
+
lines.push(' end');
|
|
809
|
+
}
|
|
810
|
+
return lines.join('\n');
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* Sanitize string for use as Mermaid node ID
|
|
814
|
+
*/
|
|
815
|
+
sanitizeId(str) {
|
|
816
|
+
return str.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Convert kebab-case to Title Case
|
|
820
|
+
*/
|
|
821
|
+
titleCase(str) {
|
|
822
|
+
return str
|
|
823
|
+
.split('-')
|
|
824
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
825
|
+
.join(' ');
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Truncate string to max length
|
|
829
|
+
*/
|
|
830
|
+
truncate(str, maxLen) {
|
|
831
|
+
if (str.length <= maxLen)
|
|
832
|
+
return str;
|
|
833
|
+
return str.slice(0, maxLen - 3) + '...';
|
|
834
|
+
}
|
|
307
835
|
}
|
|
308
836
|
//# sourceMappingURL=photon-doc-extractor.js.map
|