@geminixiang/mikan 1.0.0-beta.45 → 1.0.0-beta.46
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/CHANGELOG.md +26 -0
- package/README.md +12 -19
- package/dist/adapter.d.ts +1 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +3 -1
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +143 -141
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/discord/context.d.ts +2 -8
- package/dist/adapters/discord/context.d.ts.map +1 -1
- package/dist/adapters/discord/context.js +1 -1
- package/dist/adapters/discord/context.js.map +1 -1
- package/dist/adapters/discord/format.d.ts.map +1 -1
- package/dist/adapters/discord/format.js +2 -4
- package/dist/adapters/discord/format.js.map +1 -1
- package/dist/adapters/github/bot.d.ts.map +1 -1
- package/dist/adapters/github/bot.js +1 -4
- package/dist/adapters/github/bot.js.map +1 -1
- package/dist/adapters/github/context.d.ts +2 -9
- package/dist/adapters/github/context.d.ts.map +1 -1
- package/dist/adapters/github/context.js.map +1 -1
- package/dist/adapters/github/github-ops.d.ts +4 -17
- package/dist/adapters/github/github-ops.d.ts.map +1 -1
- package/dist/adapters/github/github-ops.js +17 -86
- package/dist/adapters/github/github-ops.js.map +1 -1
- package/dist/adapters/github/tool-pack.d.ts.map +1 -1
- package/dist/adapters/github/tool-pack.js +0 -1
- package/dist/adapters/github/tool-pack.js.map +1 -1
- package/dist/adapters/github/tools/checks.d.ts +0 -1
- package/dist/adapters/github/tools/checks.d.ts.map +1 -1
- package/dist/adapters/github/tools/checks.js +3 -22
- package/dist/adapters/github/tools/checks.js.map +1 -1
- package/dist/adapters/github/types.d.ts +0 -33
- package/dist/adapters/github/types.d.ts.map +1 -1
- package/dist/adapters/github/types.js.map +1 -1
- package/dist/adapters/progressive-renderer.d.ts.map +1 -1
- package/dist/adapters/progressive-renderer.js +311 -318
- package/dist/adapters/progressive-renderer.js.map +1 -1
- package/dist/adapters/slack/blocks.d.ts.map +1 -1
- package/dist/adapters/slack/blocks.js +1 -4
- package/dist/adapters/slack/blocks.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +12 -0
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +158 -178
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/context.d.ts +2 -8
- package/dist/adapters/slack/context.d.ts.map +1 -1
- package/dist/adapters/slack/context.js +1 -1
- package/dist/adapters/slack/context.js.map +1 -1
- package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +135 -123
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/slack/stream-limits.d.ts +1 -1
- package/dist/adapters/slack/stream-limits.js +1 -1
- package/dist/adapters/slack/stream-limits.js.map +1 -1
- package/dist/adapters/slack/types.d.ts +4 -0
- package/dist/adapters/slack/types.d.ts.map +1 -1
- package/dist/adapters/slack/types.js.map +1 -1
- package/dist/adapters/telegram/context.d.ts +2 -8
- package/dist/adapters/telegram/context.d.ts.map +1 -1
- package/dist/adapters/telegram/context.js +1 -2
- package/dist/adapters/telegram/context.js.map +1 -1
- package/dist/adapters/types.d.ts +11 -5
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/agent/catalog.d.ts +6 -18
- package/dist/agent/catalog.d.ts.map +1 -1
- package/dist/agent/catalog.js +19 -155
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/execution.d.ts +0 -7
- package/dist/agent/execution.d.ts.map +1 -1
- package/dist/agent/execution.js +23 -21
- package/dist/agent/execution.js.map +1 -1
- package/dist/agent/presenter.d.ts +7 -9
- package/dist/agent/presenter.d.ts.map +1 -1
- package/dist/agent/presenter.js +355 -357
- package/dist/agent/presenter.js.map +1 -1
- package/dist/agent/prompt.d.ts +5 -12
- package/dist/agent/prompt.d.ts.map +1 -1
- package/dist/agent/prompt.js +56 -81
- package/dist/agent/prompt.js.map +1 -1
- package/dist/agent/runner.d.ts +0 -7
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +255 -308
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/types.d.ts +21 -17
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js +0 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/cli/boot.d.ts.map +1 -1
- package/dist/cli/boot.js +7 -10
- package/dist/cli/boot.js.map +1 -1
- package/dist/cli/onboard.d.ts +10 -0
- package/dist/cli/onboard.d.ts.map +1 -0
- package/dist/cli/onboard.js +237 -0
- package/dist/cli/onboard.js.map +1 -0
- package/dist/cli/types.d.ts +8 -3
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli/types.js.map +1 -1
- package/dist/commands/auto-reply.d.ts.map +1 -1
- package/dist/commands/auto-reply.js +5 -12
- package/dist/commands/auto-reply.js.map +1 -1
- package/dist/commands/manifest.d.ts.map +1 -1
- package/dist/commands/manifest.js +9 -16
- package/dist/commands/manifest.js.map +1 -1
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +15 -10
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/registry.d.ts.map +1 -1
- package/dist/commands/registry.js +0 -2
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +89 -70
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/session-view.js +9 -2
- package/dist/commands/session-view.js.map +1 -1
- package/dist/commands/types.d.ts +4 -3
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/types.js.map +1 -1
- package/dist/config.d.ts +13 -17
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +39 -37
- package/dist/config.js.map +1 -1
- package/dist/dream/index.d.ts +20 -0
- package/dist/dream/index.d.ts.map +1 -0
- package/dist/dream/index.js +253 -0
- package/dist/dream/index.js.map +1 -0
- package/dist/dream/types.d.ts +30 -0
- package/dist/dream/types.d.ts.map +1 -0
- package/dist/dream/types.js.map +1 -0
- package/dist/env-manifest.d.ts.map +1 -1
- package/dist/env-manifest.js +2 -34
- package/dist/env-manifest.js.map +1 -1
- package/dist/execution-resolver.d.ts +9 -2
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +26 -27
- package/dist/execution-resolver.js.map +1 -1
- package/dist/harness/event-format.d.ts +1 -2
- package/dist/harness/event-format.d.ts.map +1 -1
- package/dist/harness/event-format.js +9 -15
- package/dist/harness/event-format.js.map +1 -1
- package/dist/harness/index.d.ts +1 -7
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +0 -4
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/models.d.ts.map +1 -1
- package/dist/harness/models.js +15 -35
- package/dist/harness/models.js.map +1 -1
- package/dist/harness/runner.d.ts +7 -16
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +13 -131
- package/dist/harness/runner.js.map +1 -1
- package/dist/harness/session-store.d.ts +1 -1
- package/dist/harness/session-store.d.ts.map +1 -1
- package/dist/harness/session-store.js +1 -1
- package/dist/harness/session-store.js.map +1 -1
- package/dist/harness/subagent-runner.d.ts +2 -2
- package/dist/harness/subagent-runner.d.ts.map +1 -1
- package/dist/harness/subagent-runner.js +157 -162
- package/dist/harness/subagent-runner.js.map +1 -1
- package/dist/harness/types.d.ts +1 -13
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/index.d.ts +3 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/dist/main.js +31 -212
- package/dist/main.js.map +1 -1
- package/dist/mcp/catalog.d.ts +5 -0
- package/dist/mcp/catalog.d.ts.map +1 -0
- package/dist/mcp/catalog.js +135 -0
- package/dist/mcp/catalog.js.map +1 -0
- package/dist/mcp/loader.d.ts.map +1 -1
- package/dist/mcp/loader.js +3 -6
- package/dist/mcp/loader.js.map +1 -1
- package/dist/mcp/types.d.ts +22 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/office/index.d.ts +136 -8
- package/dist/office/index.d.ts.map +1 -1
- package/dist/office/index.js +1050 -9
- package/dist/office/index.js.map +1 -1
- package/dist/office/types.d.ts +19 -1
- package/dist/office/types.d.ts.map +1 -1
- package/dist/office/types.js.map +1 -1
- package/dist/packages/index.d.ts +168 -5
- package/dist/packages/index.d.ts.map +1 -1
- package/dist/packages/index.js +749 -5
- package/dist/packages/index.js.map +1 -1
- package/dist/packages/types.d.ts +1 -5
- package/dist/packages/types.d.ts.map +1 -1
- package/dist/packages/types.js.map +1 -1
- package/dist/provisioner.d.ts +2 -9
- package/dist/provisioner.d.ts.map +1 -1
- package/dist/provisioner.js +3 -12
- package/dist/provisioner.js.map +1 -1
- package/dist/runtime/conversation-runtime.d.ts.map +1 -1
- package/dist/runtime/conversation-runtime.js +117 -380
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/session-lifecycle.d.ts +32 -18
- package/dist/runtime/session-lifecycle.d.ts.map +1 -1
- package/dist/runtime/session-lifecycle.js +159 -46
- package/dist/runtime/session-lifecycle.js.map +1 -1
- package/dist/runtime/types.d.ts +4 -26
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sandbox/cloudflare.d.ts.map +1 -1
- package/dist/sandbox/cloudflare.js +2 -3
- package/dist/sandbox/cloudflare.js.map +1 -1
- package/dist/sandbox/container.d.ts +0 -1
- package/dist/sandbox/container.d.ts.map +1 -1
- package/dist/sandbox/container.js +2 -3
- package/dist/sandbox/container.js.map +1 -1
- package/dist/sandbox/host.d.ts.map +1 -1
- package/dist/sandbox/host.js +4 -2
- package/dist/sandbox/host.js.map +1 -1
- package/dist/sandbox/identity.d.ts +10 -19
- package/dist/sandbox/identity.d.ts.map +1 -1
- package/dist/sandbox/identity.js +8 -8
- package/dist/sandbox/identity.js.map +1 -1
- package/dist/sandbox/index.d.ts +7 -10
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +45 -16
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +13 -45
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/sandbox/utils.d.ts +5 -0
- package/dist/sandbox/utils.d.ts.map +1 -1
- package/dist/sandbox/utils.js +10 -0
- package/dist/sandbox/utils.js.map +1 -1
- package/dist/sessions/chat-history-sync.d.ts +1 -3
- package/dist/sessions/chat-history-sync.d.ts.map +1 -1
- package/dist/sessions/chat-history-sync.js +58 -11
- package/dist/sessions/chat-history-sync.js.map +1 -1
- package/dist/sessions/migrate-v3.d.ts +2 -5
- package/dist/sessions/migrate-v3.d.ts.map +1 -1
- package/dist/sessions/migrate-v3.js +17 -1
- package/dist/sessions/migrate-v3.js.map +1 -1
- package/dist/sessions/store.d.ts +5 -6
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js +62 -2
- package/dist/sessions/store.js.map +1 -1
- package/dist/sessions/types.d.ts +9 -0
- package/dist/sessions/types.d.ts.map +1 -1
- package/dist/sessions/types.js.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +2 -10
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/read.js +2 -2
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/sandbox.d.ts.map +1 -1
- package/dist/tools/sandbox.js +2 -3
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/subagent.d.ts +1 -1
- package/dist/tools/subagent.js.map +1 -1
- package/dist/types.d.ts +38 -127
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault/index.d.ts +9 -2
- package/dist/vault/index.d.ts.map +1 -1
- package/dist/vault/index.js +29 -5
- package/dist/vault/index.js.map +1 -1
- package/dist/web/admin/portal.d.ts +12 -1
- package/dist/web/admin/portal.d.ts.map +1 -1
- package/dist/web/admin/portal.js +437 -422
- package/dist/web/admin/portal.js.map +1 -1
- package/dist/web/admin/types.d.ts +2 -2
- package/dist/web/admin/types.d.ts.map +1 -1
- package/dist/web/admin/types.js.map +1 -1
- package/dist/web/login/portal.d.ts +7 -1
- package/dist/web/login/portal.d.ts.map +1 -1
- package/dist/web/login/portal.js +143 -78
- package/dist/web/login/portal.js.map +1 -1
- package/dist/web/portal-shell.d.ts +1 -0
- package/dist/web/portal-shell.d.ts.map +1 -1
- package/dist/web/portal-shell.js +12 -1
- package/dist/web/portal-shell.js.map +1 -1
- package/dist/web/server.d.ts +3 -3
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js.map +1 -1
- package/dist/web/session-view/portal.d.ts +8 -1
- package/dist/web/session-view/portal.d.ts.map +1 -1
- package/dist/web/session-view/portal.js +609 -132
- package/dist/web/session-view/portal.js.map +1 -1
- package/dist/web/session-view/types.d.ts +8 -0
- package/dist/web/session-view/types.d.ts.map +1 -1
- package/dist/web/session-view/types.js.map +1 -1
- package/dist/workspace-projection/index.d.ts +14 -2
- package/dist/workspace-projection/index.d.ts.map +1 -1
- package/dist/workspace-projection/index.js +102 -14
- package/dist/workspace-projection/index.js.map +1 -1
- package/dist/workspace-projection/types.d.ts +14 -1
- package/dist/workspace-projection/types.d.ts.map +1 -1
- package/dist/workspace-projection/types.js.map +1 -1
- package/package.json +3 -5
- package/dist/adapters/github/cloudbuild.d.ts +0 -19
- package/dist/adapters/github/cloudbuild.d.ts.map +0 -1
- package/dist/adapters/github/cloudbuild.js +0 -71
- package/dist/adapters/github/cloudbuild.js.map +0 -1
- package/dist/adapters/github/gcp-auth.d.ts +0 -28
- package/dist/adapters/github/gcp-auth.d.ts.map +0 -1
- package/dist/adapters/github/gcp-auth.js +0 -196
- package/dist/adapters/github/gcp-auth.js.map +0 -1
- package/dist/agent/index.d.ts +0 -9
- package/dist/agent/index.d.ts.map +0 -1
- package/dist/agent/index.js +0 -8
- package/dist/agent/index.js.map +0 -1
- package/dist/cli/ext-dev.d.ts +0 -2
- package/dist/cli/ext-dev.d.ts.map +0 -1
- package/dist/cli/ext-dev.js +0 -188
- package/dist/cli/ext-dev.js.map +0 -1
- package/dist/cli/ext.d.ts +0 -2
- package/dist/cli/ext.d.ts.map +0 -1
- package/dist/cli/ext.js +0 -324
- package/dist/cli/ext.js.map +0 -1
- package/dist/commands/extensions.d.ts +0 -26
- package/dist/commands/extensions.d.ts.map +0 -1
- package/dist/commands/extensions.js +0 -103
- package/dist/commands/extensions.js.map +0 -1
- package/dist/extension-schedules.d.ts +0 -31
- package/dist/extension-schedules.d.ts.map +0 -1
- package/dist/extension-schedules.js +0 -229
- package/dist/extension-schedules.js.map +0 -1
- package/dist/harness/auth.d.ts +0 -17
- package/dist/harness/auth.d.ts.map +0 -1
- package/dist/harness/auth.js +0 -92
- package/dist/harness/auth.js.map +0 -1
- package/dist/harness/extensions/loader.d.ts +0 -40
- package/dist/harness/extensions/loader.d.ts.map +0 -1
- package/dist/harness/extensions/loader.js +0 -723
- package/dist/harness/extensions/loader.js.map +0 -1
- package/dist/harness/extensions/registry.d.ts +0 -155
- package/dist/harness/extensions/registry.d.ts.map +0 -1
- package/dist/harness/extensions/registry.js +0 -420
- package/dist/harness/extensions/registry.js.map +0 -1
- package/dist/harness/extensions/types.d.ts +0 -665
- package/dist/harness/extensions/types.d.ts.map +0 -1
- package/dist/harness/extensions/types.js.map +0 -1
- package/dist/office/address.d.ts +0 -31
- package/dist/office/address.d.ts.map +0 -1
- package/dist/office/address.js +0 -113
- package/dist/office/address.js.map +0 -1
- package/dist/office/layout.d.ts +0 -27
- package/dist/office/layout.d.ts.map +0 -1
- package/dist/office/layout.js +0 -97
- package/dist/office/layout.js.map +0 -1
- package/dist/office/migration.d.ts +0 -44
- package/dist/office/migration.d.ts.map +0 -1
- package/dist/office/migration.js +0 -255
- package/dist/office/migration.js.map +0 -1
- package/dist/office/registry.d.ts +0 -75
- package/dist/office/registry.d.ts.map +0 -1
- package/dist/office/registry.js +0 -646
- package/dist/office/registry.js.map +0 -1
- package/dist/packages/admin.d.ts +0 -17
- package/dist/packages/admin.d.ts.map +0 -1
- package/dist/packages/admin.js +0 -98
- package/dist/packages/admin.js.map +0 -1
- package/dist/packages/inspect.d.ts +0 -11
- package/dist/packages/inspect.d.ts.map +0 -1
- package/dist/packages/inspect.js +0 -98
- package/dist/packages/inspect.js.map +0 -1
- package/dist/packages/materialize.d.ts +0 -40
- package/dist/packages/materialize.d.ts.map +0 -1
- package/dist/packages/materialize.js +0 -297
- package/dist/packages/materialize.js.map +0 -1
- package/dist/packages/resolve.d.ts +0 -25
- package/dist/packages/resolve.d.ts.map +0 -1
- package/dist/packages/resolve.js +0 -208
- package/dist/packages/resolve.js.map +0 -1
- package/dist/packages/source.d.ts +0 -39
- package/dist/packages/source.d.ts.map +0 -1
- package/dist/packages/source.js +0 -189
- package/dist/packages/source.js.map +0 -1
- package/dist/sandbox/errors.d.ts +0 -6
- package/dist/sandbox/errors.d.ts.map +0 -1
- package/dist/sandbox/errors.js +0 -11
- package/dist/sandbox/errors.js.map +0 -1
- package/dist/sandbox/firecracker.d.ts +0 -18
- package/dist/sandbox/firecracker.d.ts.map +0 -1
- package/dist/sandbox/firecracker.js +0 -223
- package/dist/sandbox/firecracker.js.map +0 -1
- package/dist/sandbox/gondolin.d.ts +0 -57
- package/dist/sandbox/gondolin.d.ts.map +0 -1
- package/dist/sandbox/gondolin.js +0 -764
- package/dist/sandbox/gondolin.js.map +0 -1
- package/dist/sandbox/image.d.ts +0 -3
- package/dist/sandbox/image.d.ts.map +0 -1
- package/dist/sandbox/image.js +0 -29
- package/dist/sandbox/image.js.map +0 -1
- package/dist/sessions/conversation-log.d.ts +0 -9
- package/dist/sessions/conversation-log.d.ts.map +0 -1
- package/dist/sessions/conversation-log.js +0 -50
- package/dist/sessions/conversation-log.js.map +0 -1
- package/dist/sessions/rotation.d.ts +0 -2
- package/dist/sessions/rotation.d.ts.map +0 -1
- package/dist/sessions/rotation.js +0 -41
- package/dist/sessions/rotation.js.map +0 -1
- package/dist/vault/disabled.d.ts +0 -9
- package/dist/vault/disabled.d.ts.map +0 -1
- package/dist/vault/disabled.js +0 -25
- package/dist/vault/disabled.js.map +0 -1
- package/dist/web/admin/store.d.ts +0 -13
- package/dist/web/admin/store.d.ts.map +0 -1
- package/dist/web/admin/store.js +0 -14
- package/dist/web/admin/store.js.map +0 -1
- package/dist/web/login/store.d.ts +0 -8
- package/dist/web/login/store.d.ts.map +0 -1
- package/dist/web/login/store.js +0 -15
- package/dist/web/login/store.js.map +0 -1
- package/dist/web/session-view/service.d.ts +0 -6
- package/dist/web/session-view/service.d.ts.map +0 -1
- package/dist/web/session-view/service.js +0 -517
- package/dist/web/session-view/service.js.map +0 -1
- package/dist/web/session-view/store.d.ts +0 -8
- package/dist/web/session-view/store.d.ts.map +0 -1
- package/dist/web/session-view/store.js +0 -15
- package/dist/web/session-view/store.js.map +0 -1
- /package/dist/{harness/extensions → dream}/types.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../../../src/adapters/github/bot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,uBAAuB,EAA0B,MAAM,kBAAkB,CAAC;AACnF,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAe,MAAM,uBAAuB,CAAC;AACzE,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,UAAU,CAAC;AAWlB,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC;IAClC,KAAK,EAAE,IAAI,CAAC,MAAM,CAChB,IAAI,CAAC,MAAM,EAAE,EACb,IAAI,CAAC,MAAM,CAAC;QACV,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;QACrB,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACvC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACrC,wEAAwE;QACxE,0EAA0E;QAC1E,kBAAkB,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;KAC7D,CAAC,CACH;CACF,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEtC,MAAM,YAAY,GAAG,IAAI,CAAC;AAE1B,oEAAoE;AACpE,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAEtC,8DAA8D;AAC9D,MAAM,eAAe,GAAG;IACtB,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,CAAC;CACT,CAAC;AAEF;;;;GAIG;AACH,MAAM,qBAAqB,GAAG,eAAe,CAAC,KAAK,CAAC;AAEpD,gFAAgF;AAChF,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,eAAe,CAAC,IAAoC,CAAC,IAAI,CAAC,CAAC;AACpE,CAAC;AAED,6DAA6D;AAC7D,MAAM,uBAAuB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAW9C,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,eAAe,OAAO,IAAI,CAAC;AAEhG,sEAAsE;AACtE,MAAM,gBAAgB,GAA0C;IAC9D,IAAI,EAAE,IAAI;IACV,QAAQ,EAAE,IAAI;IACd,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;CACb,CAAC;AAqBF,sEAAsE;AACtE,6EAA6E;AAC7E,wEAAwE;AACxE,SAAS,aAAa,CAAC,KAAe;IACpC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACzB,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,qDAAqD,KAAK,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,SAAS,SAAS,CAAC,IAAiB;IAClC,IAAI,IAAI,CAAC,IAAI,IAAI,YAAY;QAAE,OAAO;IACtC,IAAI,MAAM,GAAG,IAAI,CAAC,IAAI,GAAG,YAAY,GAAG,CAAC,CAAC;IAC1C,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;QACtB,IAAI,MAAM,EAAE,IAAI,CAAC;YAAE,MAAM;QACzB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,mFAAmF;AACnF,SAAS,eAAe,CAAC,cAAsB;IAC7C,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACrD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,+BAA+B,cAAc,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,yEAAyE;AACzE,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACjC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC,MAAM,OAAO,kBAAkB;IAgB7B,YAAY,OAA8B,EAAE,MAAuB,EAAE,MAAqB;QAVlF,YAAO,GAAkB,IAAI,CAAC;QAC9B,aAAQ,GAAkB,IAAI,CAAC;QAC/B,iBAAY,GAAoB,EAAE,CAAC;QACnC,WAAM,GAAG,IAAI,GAAG,EAA+B,CAAC;QAChD,cAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;QAC7C,oBAAe,GAAG,IAAI,GAAG,EAA+C,CAAC;QACzE,iBAAY,GAAG,KAAK,CAAC;QACrB,gBAAW,GAAG,KAAK,CAAC;QACpB,qBAAgB,GAA0B,IAAI,CAAC;QAGrD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM;YACT,MAAM;gBACN,IAAI,YAAY,CAAC;oBACf,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,UAAU,EAAE,MAAM,CAAC,UAAU;oBAC7B,cAAc,EAAE,MAAM,CAAC,cAAc;iBACtC,CAAC,CAAC;QACL,IAAI,CAAC,GAAG,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE;YACpC,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC,CAAC;IACL,CAAC;IAED,6EAA6E;IAC7E,uCAAuC;IACvC,6EAA6E;IAE7E,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QAC9C,8EAA8E;QAC9E,sEAAsE;QACtE,0CAA0C;QAC1C,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,OAAO,OAAO,CAAC,CAAC;YACtE,IAAI,CAAC,QAAQ,GAAG,GAAG,SAAS,IAAI,IAAI,CAAC,OAAO,gCAAgC,CAAC;QAC/E,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,QAAQ,GAAG,GAAG,IAAI,CAAC,OAAO,gCAAgC,CAAC;QAClE,CAAC;QACD,IAAI,CAAC,YAAY;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;gBAC1B,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;gBAClC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,4BAA4B,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;oBACtE,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE;oBAC3C,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE;iBACpC,CAAC,CAAC,CAAC;QACV,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,GAAG,CAAC,UAAU,CAAC,2DAA2D,CAAC,CAAC;QAC9E,CAAC;QAED,yEAAyE;QACzE,0EAA0E;QAC1E,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACrC,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YACxC,IAAI,CAAC,SAAS,CAAC,GAAG,CAChB,OAAO,EACP,KAAK;gBACH,CAAC,CAAC;oBACE,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,YAAY,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC;oBACzC,UAAU,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC;oBACrC,kBAAkB,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,kBAAkB,IAAI,EAAE,CAAC;iBAC5D;gBACH,CAAC,CAAC;oBACE,QAAQ,EAAE,GAAG;oBACb,MAAM,EAAE,GAAG;oBACX,YAAY,EAAE,IAAI,GAAG,EAAE;oBACvB,UAAU,EAAE,IAAI,GAAG,EAAE;oBACrB,kBAAkB,EAAE,IAAI,GAAG,EAAE;iBAC9B,CACN,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAExB,WAAW,CAAC,GAAG,EAAE;YACf,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,KAAK,EAAE,CAAC;QAEvC,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC3B,GAAG,CAAC,OAAO,CACT,0BAA0B,IAAI,CAAC,OAAO,kBAAkB,IAAI,CAAC,YAAY,CAAC,MAAM,kBAAkB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CACnJ,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,IAAY;QAC7C,MAAM,GAAG,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,yBAAyB,EAAE,wBAAwB,CAAC,CAAC;QACnF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;QAC9D,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YAClC,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAe,EAAE,EAAU,EAAE,IAAY;QAC3D,MAAM,GAAG,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACjG,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,SAAiB,EAAE,KAAa;QACjE,MAAM,GAAG,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,qCAAqC,KAAK,iBAAiB,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACvG,CAAC;QACJ,CAAC;QACD,MAAM,eAAe,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACxD,MAAM,WAAW,CAAC,GAAG,EAAE;YACrB,IAAI,SAAS,KAAK,oBAAoB,EAAE,CAAC;gBACvC,OAAO,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACnF,CAAC;YACD,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;gBAC7B,OAAO,IAAI,CAAC,MAAM,CAAC,2BAA2B,CAC5C,GAAG,CAAC,KAAK,EACT,GAAG,CAAC,IAAI,EACR,eAAe,EACf,OAAO,CACR,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5F,CAAC,CAAC,CAAC;IACL,CAAC;IAED,YAAY,CAAC,KAAwB;QACnC,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACtB,GAAG,CAAC,UAAU,CACZ,wBAAwB,cAAc,iBAAiB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CACrF,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,wBAAwB,cAAc,KAAK,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QACtF,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;YACjB,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAoB,EAAE,IAAI,CAAC,CAAC;YACjE,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gBAAgB;QACd,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,cAAc;YAC1B,eAAe,EACb,mDAAmD;gBACnD,4FAA4F;gBAC5F,4FAA4F;YAC9F,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,EAAE;SACV,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,wCAAwC;IACxC,6EAA6E;IAE7E,KAAK,CAAC,WAAW,CAAC,GAA0B,EAAE,IAAY;QACxD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,CACrC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CACtE,CAAC;QACF,OAAO,OAAO,CAAC,EAAE,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,GAA0B,EAAE,SAAiB;QAC/D,MAAM,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IAC1F,CAAC;IAED,SAAS,CAAC,cAAsB,EAAE,KAAa;QAC7C,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;IAED,cAAc,CAAC,cAAsB,EAAE,IAAY,EAAE,EAAU;QAC7D,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,6EAA6E;IAC7E,oBAAoB;IACpB,6EAA6E;IAErE,QAAQ,CAAC,cAAsB;QACrC,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,IAAI,mBAAmB,CAAC,QAAQ,CAAC,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,UAAU,GAAG,wBAAwB;QAC/C,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB;YAAE,OAAO;QAClC,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC7B,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;IAChC,CAAC;IAED,+DAA+D;IAC/D,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC;YACH,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACrC,IAAI,CAAC;oBACH,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC;gBACnD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,GAAG,CAAC,UAAU,CACZ,0BAA0B,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,EACnD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;YAC1B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;gBACzB,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,IAAmB;QACxC,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;QACjF,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,2EAA2E;QAC3E,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QACvF,OAAO;YACL,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACnE,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;gBACtC,EAAE,EAAE,oBAAoB;gBACxB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK;gBACtB,IAAI,EAAE,KAAK,KAAK,CAAC,KAAK,OAAO,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;gBACtD,SAAS,EAAE,KAAK,CAAC,UAAU;gBAC3B,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;aAClC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;QAElB,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QAChG,OAAO;YACL,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACzE,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;gBAC/D,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBACtB,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK;gBACxB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,SAAS,EAAE,OAAO,CAAC,UAAU;aAC9B,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;QAElB,yEAAyE;QACzE,uEAAuE;QACvE,6EAA6E;QAC7E,MAAM,cAAc,GAClB,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,2BAA2B,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QACtF,OAAO;YACL,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,kBAAkB,EAAE,cAAc,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBACrF,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE;gBACnE,EAAE,EAAE,qBAAqB,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK;gBACxB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,SAAS,EAAE,OAAO,CAAC,UAAU;gBAC7B,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE;oBACN,SAAS,EAAE,OAAO,CAAC,EAAE;oBACrB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,QAAQ,EAAE,OAAO,CAAC,SAAS;oBAC3B,WAAW,EAAE,OAAO,CAAC,cAAc;iBACpC;aACF,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;QAElB,SAAS,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC9B,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC5B,SAAS,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACpC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;;OAMG;IACK,KAAK,CAAC,WAAW,CAQvB,KAAoB,EACpB,IAAiB,EACjB,KAAU,EACV,UAAqC;QAErC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;gBACnC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;gBAC/B,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;YACD,IAAI,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAE,SAAS;YACpE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK;gBAAE,SAAS;YACvC,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,6EAA6E;IAC7E,kCAAkC;IAClC,6EAA6E;IAErE,aAAa;QACnB,IAAI,CAAC;YACH,OAAO,0BAA0B,CAC/B,IAAI,CAAC,MAAM,CAAC,aAAa,EACzB,eAAe,EACf,CAAC,MAAM,EAAE,EAAE,CAAC,kCAAkC,IAAI,CAAC,MAAM,CAAC,aAAa,KAAK,MAAM,EAAE,CACrF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,oEAAoE;YACpE,oDAAoD;YACpD,GAAG,CAAC,UAAU,CACZ,wCAAwC,EACxC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;YACF,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,iFAAiF;IACjF,iBAAiB;QACf,MAAM,KAAK,GAAoB,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC7C,KAAK,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClD,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG;gBACrB,QAAQ,EAAE,SAAS,CAAC,QAAQ;gBAC5B,MAAM,EAAE,SAAS,CAAC,MAAM;gBACxB,YAAY,EAAE,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC;gBACzC,UAAU,EAAE,CAAC,GAAG,SAAS,CAAC,UAAU,CAAC;gBACrC,kBAAkB,EAAE,CAAC,GAAG,SAAS,CAAC,kBAAkB,CAAC;aACtD,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,gBAAgB;QACtB,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;QACpD,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;IAC9F,CAAC;IAED,6EAA6E;IAC7E,uBAAuB;IACvB,6EAA6E;IAE7E,0EAA0E;IAClE,cAAc;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,CAAC;IAEO,WAAW,CAAC,IAAY;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACtC,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC9C,CAAC;IAEO,YAAY,CAAC,IAAY;QAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACtC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7D,CAAC;IAED,2EAA2E;IACnE,MAAM,CAAC,cAAsB;QACnC,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC;IACrF,CAAC;IAEO,eAAe,CAAC,cAAsB;QAC5C,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,oBAAoB,CAAC,GAA0B,EAAE,IAAY;QACzE,MAAM,QAAQ,GAAG,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;YAC5C,OAAO,MAAM,CAAC,IAAI,IAAI,qBAAqB,CAAC;QAC9C,CAAC;QACD,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,CAClC,IAAI,CAAC,MAAM,CAAC,yBAAyB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CACjE,CAAC;YACF,sEAAsE;YACtE,sEAAsE;YACtE,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAC7F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CACZ,wCAAwC,IAAI,OAAO,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,mBAAmB,EAC3F,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE;YACjC,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,uBAAuB;SAChD,CAAC,CAAC;QACH,OAAO,IAAI,IAAI,qBAAqB,CAAC;IACvC,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,IAAkB;QAC7C,MAAM,cAAc,GAAG,yBAAyB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;QAC3D,sEAAsE;QACtE,yEAAyE;QACzE,gEAAgE;QAChE,IAAI,CAAC,SAAS,IAAI,CAAC,aAAa;YAAE,OAAO;QAEzC,yEAAyE;QACzE,wEAAwE;QACxE,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC5D,GAAG,CAAC,OAAO,CACT,oBAAoB,cAAc,iBAAiB,IAAI,CAAC,IAAI,2BAA2B,CACxF,CAAC;YACF,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,qBAAqB,CAAC;YACvC,cAAc;YACd,gBAAgB,EAAE,QAAQ;YAC1B,SAAS,EAAE,IAAI,CAAC,EAAE;YAClB,kBAAkB,EAAE,IAAI;SACzB,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM;YAC7B,CAAC,CAAC,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,WAAW,CAAC;YACnD,CAAC,CAAC,WAAW,CAAC;QAEhB,MAAM,SAAS,GAAG,uBAAuB,CAAC;YACxC,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,IAAI,CAAC,EAAE,KAAK,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;YAC5D,cAAc;YACd,gBAAgB,EAAE,QAAQ;YAC1B,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,UAAU;YACV,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,IAAI,EAAE,WAAW;SAClB,CAAgB,CAAC;QAElB,MAAM,oBAAoB,CAAC;YACzB,SAAS;YACT,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC;YAC7C,oBAAoB,EAAE,KAAK;YAC3B,sEAAsE;YACtE,SAAS,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE;YAC9E,UAAU,EAAE,OAAO;YACnB,YAAY,EAAE;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS;gBACpB,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,IAAI,EAAE,WAAW;gBACjB,cAAc,EAAE,KAAK;aACtB;YACD,uEAAuE;YACvE,sEAAsE;YACtE,kEAAkE;YAClE,wEAAwE;YACxE,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;gBACb,IAAI,CAAC,aAAa,IAAI,cAAc,CAAC,WAAW,CAAC,KAAK,MAAM;oBAAE,OAAO;gBACrE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;YACxC,CAAC;YACD,mEAAmE;YACnE,qEAAqE;YACrE,2CAA2C;YAC3C,kBAAkB,EAAE,KAAK,IAAI,EAAE;gBAC7B,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;gBACpE,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,QAAQ,EAAE,cAAc;YACxB,OAAO,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;YAClE,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,GAAG,EAAE,IAAI;YACT,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC;SAC5D,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACK,KAAK,CAAC,mBAAmB,CAC/B,IAAkB,EAClB,cAAsB,EACtB,aAAsB;QAEtB,IAAI,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,EAAE,KAAK,oBAAoB,EAAE,CAAC;YACvD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YACnF,uEAAuE;YACvE,2EAA2E;YAC3E,IAAI,KAAK,IAAI,QAAQ,KAAK,SAAS;gBAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAClE,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,mBAAmB,CAAC,IAAkB,EAAE,WAAmB;QACvE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAO,CAAC;QAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;QACtF,MAAM,KAAK,GAAG,CAAC,sBAAsB,qBAAqB,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,QAAQ,GAAG,CAAC,CAAC;QAChG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,IAAI,GACR,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,mBAAmB;gBAC1C,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,mBAAmB,CAAC,EAAE;gBACnD,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,UAAU,CAAC,CAAC;QAC5C,CAAC;QACD,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACrC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;YAC7F,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,mBAAmB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,mBAAmB,CAC/B,GAA0B,EAC1B,MAAc,EACd,QAAgB;QAEhB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,CACjC,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CACpE,CAAC;YACF,OAAO,GAAG;iBACP,MAAM,CACL,CAAC,OAAO,EAAE,EAAE,CACV,CAAC,OAAO,CAAC,EAAE,KAAK,MAAM,IAAI,OAAO,CAAC,cAAc,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,EAAE,GAAG,QAAQ,CACxF;iBACA,KAAK,CAAC,CAAC,gBAAgB,CAAC;iBACxB,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;gBACf,MAAM,IAAI,GACR,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,qBAAqB;oBACzC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC,GAAG;oBACpD,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;gBACnB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC3C,CAAC,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CACZ,qDAAqD,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,MAAM,EAAE,EAC1F,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;YACF,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,eAAe,CAC3B,GAA0B,EAC1B,cAAsB,EACtB,gBAAwB;QAExB,IAAI,KAAkB,CAAC;QACvB,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QACzF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CACZ,6CAA6C,cAAc,EAAE,EAC7D,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,0EAA0E;QAC1E,oEAAoE;QACpE,wEAAwE;QACxE,kDAAkD;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC/C,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3F,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE;YAC7B,IAAI,EAAE,WAAW,CAAC,WAAW,EAAE;YAC/B,EAAE,EAAE,oBAAoB;YACxB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK;YACtB,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK;YAC1B,IAAI,EAAE,KAAK,KAAK,CAAC,KAAK,OAAO,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;YACtD,WAAW,EAAE,EAAE;YACf,cAAc,EAAE,KAAK;SACtB,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC;IAED,6EAA6E;IAC7E,aAAa;IACb,6EAA6E;IAE7E;;;;OAIG;IACK,KAAK,CAAC,eAAe,CAC3B,GAA0B,EAC1B,cAAsB,EACtB,IAAa;QAEb,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO;QAC5B,IAAI,CAAC;YACH,MAAM,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,6BAA6B,CAAC,GAAG,CAAC,IAAI,EAAE;gBACtE,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAC;YACH,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAClF,MAAM,SAAS,CAAC;gBACd,GAAG,EAAE,sBAAsB,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,MAAM;gBACtD,GAAG;gBACH,KAAK;gBACL,QAAQ,EAAE,GAAG,IAAI,CAAC,OAAO,OAAO;gBAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,GAAG,IAAI,CAAC,OAAO,gCAAgC;gBAC1E,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;gBACvC,YAAY;aACb,CAAC,CAAC;YACH,GAAG,CAAC,OAAO,CACT,IAAI,cAAc,YAAY,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,wBAAwB,GAAG,CAAC,MAAM,YAAY,YAAY,IAAI,MAAM,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACvJ,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,CACZ,iCAAiC,cAAc,EAAE,EACjD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACjD,CAAC;QACJ,CAAC;IACH,CAAC;CACF","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { MessagingBot, MessagingEventHandler, MessagingInfo } from \"../../adapter.js\";\nimport { createConversationEvent, type ConversationEvent } from \"../../adapter.js\";\nimport * as log from \"../../log.js\";\nimport { ensureDirExists, readJsonSchemaFileIfExists } from \"../../utils/file-guards.js\";\nimport { atomicWritePrivateFile } from \"../../utils/file-guards.js\";\nimport { resolveChatSessionKey } from \"../../sessions/session-key.js\";\nimport {\n appendBotResponseLog,\n appendChannelLog,\n MessagingEventQueue,\n splitText,\n} from \"../shared.js\";\nimport { matchMagicWord, processMessageIntake } from \"../intake.js\";\nimport { GithubClient, GITHUB_MAX_COMMENT_LENGTH, githubRetry } from \"./client.js\";\nimport { createGithubAdapters } from \"./context.js\";\nimport { fetchIsPr, fetchPrHeadBranch, GithubOps } from \"./github-ops.js\";\nimport { cloneRepo, conversationRepoDir } from \"./repo.js\";\nimport { createOfficeAddress, type Office } from \"../../office/index.js\";\nimport {\n buildGithubConversationId,\n GITHUB_ISSUE_BODY_TS,\n githubReviewCommentTs,\n parseGithubConversationId,\n parseReviewCommentTs,\n} from \"./ids.js\";\nimport type {\n GithubBotConfig,\n GithubConversationRef,\n GithubEvent,\n GithubIssue,\n GithubReactionContent,\n GithubRepoRef,\n GithubSyncState,\n} from \"./types.js\";\n\nconst SyncStateSchema = Type.Object({\n repos: Type.Record(\n Type.String(),\n Type.Object({\n baseline: Type.String(),\n cursor: Type.String(),\n seenComments: Type.Array(Type.Number()),\n seenIssues: Type.Array(Type.Number()),\n // Optional: state files written before review-comment polling must keep\n // loading — a schema failure re-baselines and silently drops dedup state.\n seenReviewComments: Type.Optional(Type.Array(Type.Number())),\n }),\n ),\n});\n\n/**\n * Re-fetch this far behind the cursor each poll. Dedup is by id (the\n * watermark), so the overlap only costs bandwidth and closes the boundary\n * races of a bare `since` timestamp (DESIGN.md § Event source).\n */\nconst POLL_OVERLAP_MS = 5 * 60 * 1000;\n\nconst MAX_SEEN_IDS = 5000;\n\n/** Webhook pokes within this window collapse into one poll tick. */\nconst REQUEST_POLL_DEBOUNCE_MS = 1500;\n\n/** Effective role → rank, for the trigger-permission gate. */\nconst PERMISSION_RANK = {\n none: 0,\n read: 1,\n triage: 2,\n write: 3,\n maintain: 4,\n admin: 5,\n};\n\n/**\n * Commenters need write or better to trigger the agent. Fixed, not a config\n * knob: it guards public repos (anyone can comment there), and the people who\n * ask an agent to change code are exactly the people with push access.\n */\nconst REQUIRED_TRIGGER_RANK = PERMISSION_RANK.write;\n\n/** Rank for an arbitrary API-reported permission name; unknown names rank 0. */\nfunction rankOfPermission(name: string): number {\n return PERMISSION_RANK[name as keyof typeof PERMISSION_RANK] ?? 0;\n}\n\n/** Permission lookups are cached this long per repo+user. */\nconst PERMISSION_CACHE_TTL_MS = 5 * 60 * 1000;\n\n/** In-memory form of one repo's persisted watermark. */\ninterface RepoWatermark {\n baseline: string;\n cursor: string;\n seenComments: Set<number>;\n seenIssues: Set<number>;\n seenReviewComments: Set<number>;\n}\n\nexport const formatGithubContinuation = (partNum: number): string => `*(continued ${partNum})*`;\n\n/** Slack-style emoji short names → GitHub reaction content values. */\nconst GITHUB_REACTIONS: Record<string, GithubReactionContent> = {\n \"+1\": \"+1\",\n thumbsup: \"+1\",\n \"-1\": \"-1\",\n thumbsdown: \"-1\",\n laugh: \"laugh\",\n smile: \"laugh\",\n confused: \"confused\",\n heart: \"heart\",\n hooray: \"hooray\",\n tada: \"hooray\",\n rocket: \"rocket\",\n eyes: \"eyes\",\n};\n\ninterface IncomingItem {\n ref: GithubConversationRef;\n /** Comment id, rc-<id> for review comments, or GITHUB_ISSUE_BODY_TS for the body. */\n ts: string;\n user: string;\n text: string;\n createdAt: string;\n /** Known only for issue-body items; comment first-contact resolves it via getIssue. */\n isPr?: boolean;\n /** Present for inline PR review comments: the diff anchor to inject as context. */\n review?: {\n commentId: number;\n path: string;\n line: number | null;\n diffHunk: string;\n inReplyToId?: number;\n };\n}\n\n// Repo refs are lowercased at every entry point (env config here, the\n// installation API in start()) so conversation ids and sync-state keys never\n// depend on how a repo's name was spelled — GitHub is case-insensitive.\nfunction parseRepoList(repos: string[]): GithubRepoRef[] {\n return repos.map((entry) => {\n const [owner, repo, ...rest] = entry.split(\"/\");\n if (!owner || !repo || rest.length > 0) {\n throw new Error(`Invalid GITHUB_REPOS entry (expected owner/repo): ${entry}`);\n }\n return { owner: owner.toLowerCase(), repo: repo.toLowerCase() };\n });\n}\n\n/** Sets iterate in insertion order; drop the oldest ids once over the cap. */\nfunction pruneSeen(seen: Set<number>): void {\n if (seen.size <= MAX_SEEN_IDS) return;\n let toDrop = seen.size - MAX_SEEN_IDS / 2;\n for (const id of seen) {\n if (toDrop-- <= 0) break;\n seen.delete(id);\n }\n}\n\n/** Issue number from a comment's `issue_url` (…/repos/o/r/issues/42). */\nfunction issueNumberFromUrl(issueUrl: string): number {\n const match = /\\/issues\\/(\\d+)$/.exec(issueUrl);\n if (!match) {\n throw new Error(`Cannot parse issue number from ${issueUrl}`);\n }\n return Number(match[1]);\n}\n\n/** PR number from a review comment's `pull_request_url` (…/repos/o/r/pulls/42). */\nfunction prNumberFromUrl(pullRequestUrl: string): number {\n const match = /\\/pulls\\/(\\d+)$/.exec(pullRequestUrl);\n if (!match) {\n throw new Error(`Cannot parse PR number from ${pullRequestUrl}`);\n }\n return Number(match[1]);\n}\n\n/** Keep the tail: a review comment anchors to the hunk's final lines. */\nconst MAX_DIFF_HUNK_CHARS = 1500;\nconst MAX_THREAD_TURNS = 10;\nconst MAX_THREAD_TURN_CHARS = 500;\n\nexport class GithubMessagingBot implements MessagingBot {\n private readonly client: GithubClient;\n private readonly handler: MessagingEventHandler;\n private readonly config: GithubBotConfig;\n /** Host-side backend for the github_* tool pack; standalone from polling. */\n readonly ops: GithubOps;\n private appSlug: string | null = null;\n private botEmail: string | null = null;\n private watchedRepos: GithubRepoRef[] = [];\n private queues = new Map<string, MessagingEventQueue>();\n private repoState = new Map<string, RepoWatermark>();\n private permissionCache = new Map<string, { rank: number; expiresAt: number }>();\n private pollInFlight = false;\n private pollPending = false;\n private requestPollTimer: NodeJS.Timeout | null = null;\n\n constructor(handler: MessagingEventHandler, config: GithubBotConfig, client?: GithubClient) {\n this.handler = handler;\n this.config = config;\n this.client =\n client ??\n new GithubClient({\n appId: config.appId,\n privateKey: config.privateKey,\n installationId: config.installationId,\n });\n this.ops = new GithubOps(this.client, {\n workspace: config.workspace,\n cloudBuild: config.cloudBuild,\n });\n }\n\n // ==========================================================================\n // Public API (implements MessagingBot)\n // ==========================================================================\n\n async start(): Promise<void> {\n this.appSlug = await this.client.getAppSlug();\n // Canonical noreply author email (<user-id>+<login>@users.noreply.github.com)\n // so the bot's commits link to its avatar/profile; degrade to a plain\n // noreply spelling when the lookup fails.\n try {\n const botUserId = await this.client.getUserId(`${this.appSlug}[bot]`);\n this.botEmail = `${botUserId}+${this.appSlug}[bot]@users.noreply.github.com`;\n } catch {\n this.botEmail = `${this.appSlug}[bot]@users.noreply.github.com`;\n }\n this.watchedRepos =\n this.config.repos.length > 0\n ? parseRepoList(this.config.repos)\n : (await this.client.listInstallationRepositories()).map((repository) => ({\n owner: repository.owner.login.toLowerCase(),\n repo: repository.name.toLowerCase(),\n }));\n if (this.watchedRepos.length === 0) {\n log.logWarning(\"GitHub: installation has no repositories; nothing to poll\");\n }\n\n // Restore persisted watermarks; a repo watched for the first time gets a\n // baseline of \"now\" so history never triggers (DESIGN.md § Event source).\n const persisted = this.loadSyncState();\n const now = new Date().toISOString();\n for (const repo of this.watchedRepos) {\n const repoKey = `${repo.owner}/${repo.repo}`;\n const saved = persisted?.repos[repoKey];\n this.repoState.set(\n repoKey,\n saved\n ? {\n baseline: saved.baseline,\n cursor: saved.cursor,\n seenComments: new Set(saved.seenComments),\n seenIssues: new Set(saved.seenIssues),\n seenReviewComments: new Set(saved.seenReviewComments ?? []),\n }\n : {\n baseline: now,\n cursor: now,\n seenComments: new Set(),\n seenIssues: new Set(),\n seenReviewComments: new Set(),\n },\n );\n }\n this.persistSyncState();\n\n setInterval(() => {\n void this.poll();\n }, this.config.pollIntervalMs).unref();\n\n log.logConnected(\"GitHub\");\n log.logInfo(\n `GitHub bot started as @${this.appSlug}[bot], polling ${this.watchedRepos.length} repo(s) every ${Math.round(this.config.pollIntervalMs / 1000)}s`,\n );\n }\n\n async postMessage(channel: string, text: string): Promise<string> {\n const ref = parseGithubConversationId(channel);\n const parts = splitText(text, GITHUB_MAX_COMMENT_LENGTH, formatGithubContinuation);\n const firstId = await this.postComment(ref, parts[0] ?? text);\n for (const part of parts.slice(1)) {\n await this.postComment(ref, part);\n }\n return String(firstId);\n }\n\n async updateMessage(channel: string, ts: string, text: string): Promise<void> {\n const ref = parseGithubConversationId(channel);\n await githubRetry(() => this.client.updateIssueComment(ref.owner, ref.repo, Number(ts), text));\n }\n\n async addReaction(channel: string, messageTs: string, emoji: string): Promise<void> {\n const ref = parseGithubConversationId(channel);\n const content = GITHUB_REACTIONS[emoji.replace(/^:|:$/g, \"\")];\n if (!content) {\n throw new Error(\n `GitHub does not support reaction '${emoji}' (supported: ${Object.keys(GITHUB_REACTIONS).join(\", \")})`,\n );\n }\n const reviewCommentId = parseReviewCommentTs(messageTs);\n await githubRetry(() => {\n if (messageTs === GITHUB_ISSUE_BODY_TS) {\n return this.client.createIssueReaction(ref.owner, ref.repo, ref.number, content);\n }\n if (reviewCommentId !== null) {\n return this.client.createReviewCommentReaction(\n ref.owner,\n ref.repo,\n reviewCommentId,\n content,\n );\n }\n return this.client.createCommentReaction(ref.owner, ref.repo, Number(messageTs), content);\n });\n }\n\n enqueueEvent(event: ConversationEvent): boolean {\n const conversationId = event.conversationId;\n const queue = this.getQueue(conversationId);\n if (queue.size() >= 5) {\n log.logWarning(\n `Event queue full for ${conversationId}, discarding: ${event.text.substring(0, 50)}`,\n );\n return false;\n }\n log.logInfo(`Enqueueing event for ${conversationId}: ${event.text.substring(0, 50)}`);\n queue.enqueue(() => {\n const context = createGithubAdapters(event as GithubEvent, this);\n return this.handler.handleEvent(event, this, context);\n });\n return true;\n }\n\n getMessagingInfo(): MessagingInfo {\n return {\n name: \"github\",\n trustModel: \"open-trigger\",\n formattingGuide:\n \"## GitHub Formatting (GitHub Flavored Markdown)\\n\" +\n \"Standard Markdown plus tables, task lists, fenced code blocks, and ```suggestion blocks.\\n\" +\n \"Reference issues/PRs as #123 and users as @login (mentions notify people — use sparingly).\",\n channels: [],\n users: [],\n };\n }\n\n // ==========================================================================\n // Internal helpers (used by context.ts)\n // ==========================================================================\n\n async postComment(ref: GithubConversationRef, text: string): Promise<number> {\n const comment = await githubRetry(() =>\n this.client.createIssueComment(ref.owner, ref.repo, ref.number, text),\n );\n return comment.id;\n }\n\n async deleteComment(ref: GithubConversationRef, commentId: number): Promise<void> {\n await githubRetry(() => this.client.deleteIssueComment(ref.owner, ref.repo, commentId));\n }\n\n logToFile(conversationId: string, entry: object): void {\n appendChannelLog(this.office(conversationId), entry);\n }\n\n logBotResponse(conversationId: string, text: string, ts: string): void {\n appendBotResponseLog(this.office(conversationId), text, ts);\n }\n\n // ==========================================================================\n // Private - polling\n // ==========================================================================\n\n private getQueue(conversationId: string): MessagingEventQueue {\n let queue = this.queues.get(conversationId);\n if (!queue) {\n queue = new MessagingEventQueue(\"GitHub\");\n this.queues.set(conversationId, queue);\n }\n return queue;\n }\n\n /**\n * Webhook poke: run a poll soon. Debounced so a burst of deliveries costs\n * one tick; a poke landing mid-poll marks it pending and the tick re-runs,\n * because the in-flight pass may already be past the poked repo's feeds.\n */\n requestPoll(debounceMs = REQUEST_POLL_DEBOUNCE_MS): void {\n if (this.pollInFlight) {\n this.pollPending = true;\n return;\n }\n if (this.requestPollTimer) return;\n this.requestPollTimer = setTimeout(() => {\n this.requestPollTimer = null;\n void this.poll();\n }, debounceMs);\n this.requestPollTimer.unref();\n }\n\n /** One poll tick over every watched repo. Public for tests. */\n async poll(): Promise<void> {\n if (this.pollInFlight) {\n this.pollPending = true;\n return;\n }\n this.pollInFlight = true;\n try {\n let changed = false;\n for (const repo of this.watchedRepos) {\n try {\n changed = (await this.pollRepo(repo)) || changed;\n } catch (err) {\n log.logWarning(\n `GitHub poll failed for ${repo.owner}/${repo.repo}`,\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n if (changed) {\n this.persistSyncState();\n }\n } finally {\n this.pollInFlight = false;\n if (this.pollPending) {\n this.pollPending = false;\n this.requestPoll();\n }\n }\n }\n\n private async pollRepo(repo: GithubRepoRef): Promise<boolean> {\n const repoKey = `${repo.owner}/${repo.repo}`;\n const state = this.repoState.get(repoKey);\n if (!state) return false;\n const since = new Date(Date.parse(state.cursor) - POLL_OVERLAP_MS).toISOString();\n let changed = false;\n\n // Comment activity also bumps the parent issue's updated_at, so the issues\n // list mostly echoes the comments list; only issues *created* since the\n // baseline are new conversations (their body is the first message).\n const issues = (await this.client.listIssuesSince(repo.owner, repo.repo, since)) ?? [];\n changed =\n (await this.advanceFeed(state, state.seenIssues, issues, (issue) => ({\n ref: { ...repo, number: issue.number },\n ts: GITHUB_ISSUE_BODY_TS,\n user: issue.user.login,\n text: `# ${issue.title}\\n\\n${issue.body ?? \"\"}`.trim(),\n createdAt: issue.created_at,\n isPr: Boolean(issue.pull_request),\n }))) || changed;\n\n const comments = (await this.client.listIssueCommentsSince(repo.owner, repo.repo, since)) ?? [];\n changed =\n (await this.advanceFeed(state, state.seenComments, comments, (comment) => ({\n ref: { ...repo, number: issueNumberFromUrl(comment.issue_url) },\n ts: String(comment.id),\n user: comment.user.login,\n text: comment.body,\n createdAt: comment.created_at,\n }))) || changed;\n\n // Inline PR review comments live in their own endpoint and id space; the\n // same watermark discipline applies. The bot's own thread replies (the\n // github_review_reply tool) re-surface here and are dropped as Bot-authored.\n const reviewComments =\n (await this.client.listPullReviewCommentsSince(repo.owner, repo.repo, since)) ?? [];\n changed =\n (await this.advanceFeed(state, state.seenReviewComments, reviewComments, (comment) => ({\n ref: { ...repo, number: prNumberFromUrl(comment.pull_request_url) },\n ts: githubReviewCommentTs(comment.id),\n user: comment.user.login,\n text: comment.body,\n createdAt: comment.created_at,\n isPr: true,\n review: {\n commentId: comment.id,\n path: comment.path,\n line: comment.line,\n diffHunk: comment.diff_hunk,\n inReplyToId: comment.in_reply_to_id,\n },\n }))) || changed;\n\n pruneSeen(state.seenComments);\n pruneSeen(state.seenIssues);\n pruneSeen(state.seenReviewComments);\n return changed;\n }\n\n /**\n * One feed's watermark advance — the same discipline for all three feeds:\n * bump the cursor on any fresher updated_at, then let the id watermark plus\n * the creation baseline decide what actually triggers (edits re-surface old\n * items with a fresh updated_at). Bot-authored items advance the watermark\n * without triggering.\n */\n private async advanceFeed<\n T extends {\n id: number;\n created_at: string;\n updated_at: string;\n user: { login: string; type: string };\n },\n >(\n state: RepoWatermark,\n seen: Set<number>,\n items: T[],\n toIncoming: (item: T) => IncomingItem,\n ): Promise<boolean> {\n let changed = false;\n for (const item of items) {\n if (item.updated_at > state.cursor) {\n state.cursor = item.updated_at;\n changed = true;\n }\n if (item.created_at < state.baseline || seen.has(item.id)) continue;\n seen.add(item.id);\n changed = true;\n if (item.user.type === \"Bot\") continue;\n await this.handleIncoming(toIncoming(item));\n }\n return changed;\n }\n\n // ==========================================================================\n // Private - watermark persistence\n // ==========================================================================\n\n private loadSyncState(): GithubSyncState | undefined {\n try {\n return readJsonSchemaFileIfExists(\n this.config.syncStatePath,\n SyncStateSchema,\n (detail) => `Malformed GitHub sync state at ${this.config.syncStatePath}: ${detail}`,\n );\n } catch (err) {\n // A bad state file re-baselines (history won't trigger) rather than\n // blocking startup; the next persist overwrites it.\n log.logWarning(\n \"GitHub: ignoring unreadable sync state\",\n err instanceof Error ? err.message : String(err),\n );\n return undefined;\n }\n }\n\n /** The persisted form of the current watermarks; the test/inspection surface. */\n syncStateSnapshot(): GithubSyncState {\n const state: GithubSyncState = { repos: {} };\n for (const [repoKey, watermark] of this.repoState) {\n state.repos[repoKey] = {\n baseline: watermark.baseline,\n cursor: watermark.cursor,\n seenComments: [...watermark.seenComments],\n seenIssues: [...watermark.seenIssues],\n seenReviewComments: [...watermark.seenReviewComments],\n };\n }\n return state;\n }\n\n private persistSyncState(): void {\n ensureDirExists(dirname(this.config.syncStatePath));\n atomicWritePrivateFile(this.config.syncStatePath, JSON.stringify(this.syncStateSnapshot()));\n }\n\n // ==========================================================================\n // Private - triggering\n // ==========================================================================\n\n /** Fresh regex per call: the `g` flag makes `test`/`replace` stateful. */\n private mentionPattern(): RegExp | null {\n return this.appSlug ? new RegExp(`@${this.appSlug}(?![\\\\w-])`, \"gi\") : null;\n }\n\n private isMentioned(text: string): boolean {\n const pattern = this.mentionPattern();\n return pattern ? pattern.test(text) : false;\n }\n\n private stripMention(text: string): string {\n const pattern = this.mentionPattern();\n return (pattern ? text.replace(pattern, \"\") : text).trim();\n }\n\n /** The Conversation office for a GitHub conversation id (one PR/issue). */\n private office(conversationId: string): Office {\n return this.config.workspace.office(createOfficeAddress(\"github\", conversationId));\n }\n\n private isParticipating(conversationId: string): boolean {\n return existsSync(this.office(conversationId).logPath);\n }\n\n /**\n * True when `user` holds at least write permission on the repo. Fails\n * closed: a failed lookup denies the trigger (and logs) rather than\n * letting an unverified commenter drive the agent.\n */\n private async hasTriggerPermission(ref: GithubConversationRef, user: string): Promise<boolean> {\n const cacheKey = `${ref.owner}/${ref.repo}#${user}`;\n const cached = this.permissionCache.get(cacheKey);\n if (cached && Date.now() < cached.expiresAt) {\n return cached.rank >= REQUIRED_TRIGGER_RANK;\n }\n let rank: number;\n try {\n const role = await githubRetry(() =>\n this.client.getCollaboratorPermission(ref.owner, ref.repo, user),\n );\n // Custom role_name values are unrankable; the legacy permission field\n // still carries their closest standard mapping, so take the stronger.\n rank = Math.max(rankOfPermission(role.role_name ?? \"\"), rankOfPermission(role.permission));\n } catch (err) {\n log.logWarning(\n `GitHub: permission lookup failed for ${user} on ${ref.owner}/${ref.repo}; denying trigger`,\n err instanceof Error ? err.message : String(err),\n );\n return false;\n }\n this.permissionCache.set(cacheKey, {\n rank,\n expiresAt: Date.now() + PERMISSION_CACHE_TTL_MS,\n });\n return rank >= REQUIRED_TRIGGER_RANK;\n }\n\n private async handleIncoming(item: IncomingItem): Promise<void> {\n const conversationId = buildGithubConversationId(item.ref);\n const mentioned = this.isMentioned(item.text);\n const participating = this.isParticipating(conversationId);\n // Narrow trigger (DESIGN.md): only threads the bot is mentioned in or\n // already participates in. Everything else is ignored without logging so\n // busy repos don't grow conversation dirs for untouched issues.\n if (!mentioned && !participating) return;\n\n // Permission gate: on public repos anyone can comment, so a mention from\n // anyone below write permission is ignored entirely (no log, no state).\n if (!(await this.hasTriggerPermission(item.ref, item.user))) {\n log.logInfo(\n `GitHub: ignoring ${conversationId} comment from ${item.user} (below write permission)`,\n );\n return;\n }\n\n const cleanedText = this.stripMention(item.text);\n const sessionKey = resolveChatSessionKey({\n conversationId,\n conversationKind: \"shared\",\n messageId: item.ts,\n persistentTopLevel: true,\n });\n\n const messageText = item.review\n ? await this.formatReviewMessage(item, cleanedText)\n : cleanedText;\n\n const eventBase = createConversationEvent({\n platform: \"github\",\n type: item.ts === GITHUB_ISSUE_BODY_TS ? \"issue\" : \"message\",\n conversationId,\n conversationKind: \"shared\",\n ts: item.ts,\n sessionKey,\n user: item.user,\n userName: item.user,\n text: messageText,\n }) as GithubEvent;\n\n await processMessageIntake({\n eventBase,\n office: this.office(eventBase.conversationId),\n isAutoReplyCandidate: false,\n // Match on the user-typed text, not the review-decorated messageText.\n magicWord: { text: cleanedText, addressed: mentioned, scopeFallback: \"never\" },\n busyPolicy: \"queue\",\n logEntryBase: {\n date: item.createdAt,\n ts: item.ts,\n user: item.user,\n userName: item.user,\n text: messageText,\n isMessagingBot: false,\n },\n // log.jsonl existence is the participation authority for this adapter:\n // a first-contact magic word (\"@bot stop\" on an untouched issue) must\n // not materialize the log, or every later comment from any writer\n // would be treated as addressed to a conversation the bot never joined.\n log: (entry) => {\n if (!participating && matchMagicWord(cleanedText) === \"stop\") return;\n this.logToFile(conversationId, entry);\n },\n // GitHub has no attachments; the prep hook is used to lay down the\n // issue context and repo clone only for messages that will dispatch,\n // and before the comment itself is logged.\n processAttachments: async () => {\n await this.prepareConversation(item, conversationId, participating);\n return [];\n },\n queueKey: conversationId,\n enqueue: (queueKey, work) => this.getQueue(queueKey).enqueue(work),\n handler: this.handler,\n bot: this,\n createContext: (event) => createGithubAdapters(event, this),\n });\n }\n\n /**\n * First contact: log the issue title/body ahead of the comment so the\n * session history starts with what the thread is about. The clone is\n * (re)attempted on every trigger while ./repo is missing — a no-op once\n * it exists — so a failed first clone (e.g. App permissions granted\n * later) heals on the next mention instead of wedging the conversation.\n */\n private async prepareConversation(\n item: IncomingItem,\n conversationId: string,\n participating: boolean,\n ): Promise<void> {\n let isPrHint = item.isPr;\n if (!participating && item.ts !== GITHUB_ISSUE_BODY_TS) {\n const issue = await this.logIssueContext(item.ref, conversationId, item.createdAt);\n // Only comments arrive without the PR-ness hint; review comments carry\n // isPr: true (they only exist on PRs) and that knowledge is authoritative.\n if (issue && isPrHint === undefined) isPrHint = Boolean(issue.pull_request);\n }\n if (!existsSync(conversationRepoDir(this.office(conversationId)))) {\n const isPr = isPrHint ?? (await fetchIsPr(this.client, item.ref));\n await this.ensureRepoClone(item.ref, conversationId, isPr);\n }\n }\n\n /**\n * Decorates an inline review comment with its diff anchor and (for replies)\n * the thread's earlier turns, so the agent knows which code the feedback is\n * about without hunting through the PR. The rc-<id> in the header is what\n * github_review_reply takes to answer in-thread.\n */\n private async formatReviewMessage(item: IncomingItem, cleanedText: string): Promise<string> {\n const review = item.review!;\n const location = review.line !== null ? `${review.path}:${review.line}` : review.path;\n const parts = [`[PR review comment ${githubReviewCommentTs(review.commentId)} on ${location}]`];\n if (review.diffHunk) {\n const hunk =\n review.diffHunk.length > MAX_DIFF_HUNK_CHARS\n ? `…${review.diffHunk.slice(-MAX_DIFF_HUNK_CHARS)}`\n : review.diffHunk;\n parts.push(`\\`\\`\\`diff\\n${hunk}\\n\\`\\`\\``);\n }\n if (review.inReplyToId !== undefined) {\n const turns = await this.reviewThreadContext(item.ref, review.inReplyToId, review.commentId);\n if (turns.length > 0) {\n parts.push(`Thread so far:\\n${turns.join(\"\\n\")}`);\n }\n }\n parts.push(cleanedText);\n return parts.join(\"\\n\");\n }\n\n /**\n * Earlier turns of one review thread (root + replies before the trigger),\n * newest-truncated. Fail-soft: context is a nicety, the trigger is not.\n */\n private async reviewThreadContext(\n ref: GithubConversationRef,\n rootId: number,\n beforeId: number,\n ): Promise<string[]> {\n try {\n const all = await githubRetry(() =>\n this.client.listPullReviewComments(ref.owner, ref.repo, ref.number),\n );\n return all\n .filter(\n (comment) =>\n (comment.id === rootId || comment.in_reply_to_id === rootId) && comment.id < beforeId,\n )\n .slice(-MAX_THREAD_TURNS)\n .map((comment) => {\n const body =\n comment.body.length > MAX_THREAD_TURN_CHARS\n ? `${comment.body.slice(0, MAX_THREAD_TURN_CHARS)}…`\n : comment.body;\n return `@${comment.user.login}: ${body}`;\n });\n } catch (err) {\n log.logWarning(\n `GitHub: could not fetch review thread context for ${ref.owner}/${ref.repo}#${ref.number}`,\n err instanceof Error ? err.message : String(err),\n );\n return [];\n }\n }\n\n private async logIssueContext(\n ref: GithubConversationRef,\n conversationId: string,\n triggerCreatedAt: string,\n ): Promise<GithubIssue | null> {\n let issue: GithubIssue;\n try {\n issue = await githubRetry(() => this.client.getIssue(ref.owner, ref.repo, ref.number));\n } catch (err) {\n log.logWarning(\n `GitHub: could not fetch issue context for ${conversationId}`,\n err instanceof Error ? err.message : String(err),\n );\n return null;\n }\n // Dated just before the triggering comment, NOT issue.created_at: history\n // sync date-sorts entries and drops anything older than its recency\n // window, so an old issue's real creation date would silently evict the\n // one message that says what the thread is about.\n const triggerMs = Date.parse(triggerCreatedAt);\n const contextDate = new Date((Number.isFinite(triggerMs) ? triggerMs : Date.now()) - 1000);\n this.logToFile(conversationId, {\n date: contextDate.toISOString(),\n ts: GITHUB_ISSUE_BODY_TS,\n user: issue.user.login,\n userName: issue.user.login,\n text: `# ${issue.title}\\n\\n${issue.body ?? \"\"}`.trim(),\n attachments: [],\n isMessagingBot: false,\n });\n return issue;\n }\n\n // ==========================================================================\n // Repo clone\n // ==========================================================================\n\n /**\n * Clone the conversation's repo into its dir (bind-mounted into the\n * sandbox) using an ephemeral contents:read token that never leaves the\n * host. Non-fatal: a failed clone degrades to the pre-clone experience.\n */\n private async ensureRepoClone(\n ref: GithubConversationRef,\n conversationId: string,\n isPr: boolean,\n ): Promise<void> {\n const office = this.office(conversationId);\n const dir = conversationRepoDir(office);\n if (existsSync(dir)) return;\n try {\n office.ensure();\n const token = await this.client.createScopedInstallationToken(ref.repo, {\n contents: \"read\",\n });\n const prHeadBranch = isPr ? await fetchPrHeadBranch(this.client, ref) : undefined;\n await cloneRepo({\n url: `https://github.com/${ref.owner}/${ref.repo}.git`,\n dir,\n token,\n botLogin: `${this.appSlug}[bot]`,\n botEmail: this.botEmail ?? `${this.appSlug}[bot]@users.noreply.github.com`,\n prNumber: isPr ? ref.number : undefined,\n prHeadBranch,\n });\n log.logInfo(\n `[${conversationId}] Cloned ${ref.owner}/${ref.repo}${isPr ? ` and checked out PR #${ref.number} head as ${prHeadBranch ?? `pr-${ref.number}`}` : \"\"}`,\n );\n } catch (err) {\n log.logWarning(\n `GitHub: repo clone failed for ${conversationId}`,\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../../../src/adapters/github/bot.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { MessagingBot, MessagingEventHandler, MessagingInfo } from \"../../adapter.js\";\nimport { createConversationEvent, type ConversationEvent } from \"../../adapter.js\";\nimport * as log from \"../../log.js\";\nimport { ensureDirExists, readJsonSchemaFileIfExists } from \"../../utils/file-guards.js\";\nimport { atomicWritePrivateFile } from \"../../utils/file-guards.js\";\nimport { resolveChatSessionKey } from \"../../sessions/session-key.js\";\nimport {\n appendBotResponseLog,\n appendChannelLog,\n MessagingEventQueue,\n splitText,\n} from \"../shared.js\";\nimport { matchMagicWord, processMessageIntake } from \"../intake.js\";\nimport { GithubClient, GITHUB_MAX_COMMENT_LENGTH, githubRetry } from \"./client.js\";\nimport { createGithubAdapters } from \"./context.js\";\nimport { fetchIsPr, fetchPrHeadBranch, GithubOps } from \"./github-ops.js\";\nimport { cloneRepo, conversationRepoDir } from \"./repo.js\";\nimport { createOfficeAddress, type Office } from \"../../office/index.js\";\nimport {\n buildGithubConversationId,\n GITHUB_ISSUE_BODY_TS,\n githubReviewCommentTs,\n parseGithubConversationId,\n parseReviewCommentTs,\n} from \"./ids.js\";\nimport type {\n GithubBotConfig,\n GithubConversationRef,\n GithubEvent,\n GithubIssue,\n GithubReactionContent,\n GithubRepoRef,\n GithubSyncState,\n} from \"./types.js\";\n\nconst SyncStateSchema = Type.Object({\n repos: Type.Record(\n Type.String(),\n Type.Object({\n baseline: Type.String(),\n cursor: Type.String(),\n seenComments: Type.Array(Type.Number()),\n seenIssues: Type.Array(Type.Number()),\n // Optional: state files written before review-comment polling must keep\n // loading — a schema failure re-baselines and silently drops dedup state.\n seenReviewComments: Type.Optional(Type.Array(Type.Number())),\n }),\n ),\n});\n\n/**\n * Re-fetch this far behind the cursor each poll. Dedup is by id (the\n * watermark), so the overlap only costs bandwidth and closes the boundary\n * races of a bare `since` timestamp (DESIGN.md § Event source).\n */\nconst POLL_OVERLAP_MS = 5 * 60 * 1000;\n\nconst MAX_SEEN_IDS = 5000;\n\n/** Webhook pokes within this window collapse into one poll tick. */\nconst REQUEST_POLL_DEBOUNCE_MS = 1500;\n\n/** Effective role → rank, for the trigger-permission gate. */\nconst PERMISSION_RANK = {\n none: 0,\n read: 1,\n triage: 2,\n write: 3,\n maintain: 4,\n admin: 5,\n};\n\n/**\n * Commenters need write or better to trigger the agent. Fixed, not a config\n * knob: it guards public repos (anyone can comment there), and the people who\n * ask an agent to change code are exactly the people with push access.\n */\nconst REQUIRED_TRIGGER_RANK = PERMISSION_RANK.write;\n\n/** Rank for an arbitrary API-reported permission name; unknown names rank 0. */\nfunction rankOfPermission(name: string): number {\n return PERMISSION_RANK[name as keyof typeof PERMISSION_RANK] ?? 0;\n}\n\n/** Permission lookups are cached this long per repo+user. */\nconst PERMISSION_CACHE_TTL_MS = 5 * 60 * 1000;\n\n/** In-memory form of one repo's persisted watermark. */\ninterface RepoWatermark {\n baseline: string;\n cursor: string;\n seenComments: Set<number>;\n seenIssues: Set<number>;\n seenReviewComments: Set<number>;\n}\n\nexport const formatGithubContinuation = (partNum: number): string => `*(continued ${partNum})*`;\n\n/** Slack-style emoji short names → GitHub reaction content values. */\nconst GITHUB_REACTIONS: Record<string, GithubReactionContent> = {\n \"+1\": \"+1\",\n thumbsup: \"+1\",\n \"-1\": \"-1\",\n thumbsdown: \"-1\",\n laugh: \"laugh\",\n smile: \"laugh\",\n confused: \"confused\",\n heart: \"heart\",\n hooray: \"hooray\",\n tada: \"hooray\",\n rocket: \"rocket\",\n eyes: \"eyes\",\n};\n\ninterface IncomingItem {\n ref: GithubConversationRef;\n /** Comment id, rc-<id> for review comments, or GITHUB_ISSUE_BODY_TS for the body. */\n ts: string;\n user: string;\n text: string;\n createdAt: string;\n /** Known only for issue-body items; comment first-contact resolves it via getIssue. */\n isPr?: boolean;\n /** Present for inline PR review comments: the diff anchor to inject as context. */\n review?: {\n commentId: number;\n path: string;\n line: number | null;\n diffHunk: string;\n inReplyToId?: number;\n };\n}\n\n// Repo refs are lowercased at every entry point (env config here, the\n// installation API in start()) so conversation ids and sync-state keys never\n// depend on how a repo's name was spelled — GitHub is case-insensitive.\nfunction parseRepoList(repos: string[]): GithubRepoRef[] {\n return repos.map((entry) => {\n const [owner, repo, ...rest] = entry.split(\"/\");\n if (!owner || !repo || rest.length > 0) {\n throw new Error(`Invalid GITHUB_REPOS entry (expected owner/repo): ${entry}`);\n }\n return { owner: owner.toLowerCase(), repo: repo.toLowerCase() };\n });\n}\n\n/** Sets iterate in insertion order; drop the oldest ids once over the cap. */\nfunction pruneSeen(seen: Set<number>): void {\n if (seen.size <= MAX_SEEN_IDS) return;\n let toDrop = seen.size - MAX_SEEN_IDS / 2;\n for (const id of seen) {\n if (toDrop-- <= 0) break;\n seen.delete(id);\n }\n}\n\n/** Issue number from a comment's `issue_url` (…/repos/o/r/issues/42). */\nfunction issueNumberFromUrl(issueUrl: string): number {\n const match = /\\/issues\\/(\\d+)$/.exec(issueUrl);\n if (!match) {\n throw new Error(`Cannot parse issue number from ${issueUrl}`);\n }\n return Number(match[1]);\n}\n\n/** PR number from a review comment's `pull_request_url` (…/repos/o/r/pulls/42). */\nfunction prNumberFromUrl(pullRequestUrl: string): number {\n const match = /\\/pulls\\/(\\d+)$/.exec(pullRequestUrl);\n if (!match) {\n throw new Error(`Cannot parse PR number from ${pullRequestUrl}`);\n }\n return Number(match[1]);\n}\n\n/** Keep the tail: a review comment anchors to the hunk's final lines. */\nconst MAX_DIFF_HUNK_CHARS = 1500;\nconst MAX_THREAD_TURNS = 10;\nconst MAX_THREAD_TURN_CHARS = 500;\n\nexport class GithubMessagingBot implements MessagingBot {\n private readonly client: GithubClient;\n private readonly handler: MessagingEventHandler;\n private readonly config: GithubBotConfig;\n /** Host-side backend for the github_* tool pack; standalone from polling. */\n readonly ops: GithubOps;\n private appSlug: string | null = null;\n private botEmail: string | null = null;\n private watchedRepos: GithubRepoRef[] = [];\n private queues = new Map<string, MessagingEventQueue>();\n private repoState = new Map<string, RepoWatermark>();\n private permissionCache = new Map<string, { rank: number; expiresAt: number }>();\n private pollInFlight = false;\n private pollPending = false;\n private requestPollTimer: NodeJS.Timeout | null = null;\n\n constructor(handler: MessagingEventHandler, config: GithubBotConfig, client?: GithubClient) {\n this.handler = handler;\n this.config = config;\n this.client =\n client ??\n new GithubClient({\n appId: config.appId,\n privateKey: config.privateKey,\n installationId: config.installationId,\n });\n this.ops = new GithubOps(this.client, { workspace: config.workspace });\n }\n\n // ==========================================================================\n // Public API (implements MessagingBot)\n // ==========================================================================\n\n async start(): Promise<void> {\n this.appSlug = await this.client.getAppSlug();\n // Canonical noreply author email (<user-id>+<login>@users.noreply.github.com)\n // so the bot's commits link to its avatar/profile; degrade to a plain\n // noreply spelling when the lookup fails.\n try {\n const botUserId = await this.client.getUserId(`${this.appSlug}[bot]`);\n this.botEmail = `${botUserId}+${this.appSlug}[bot]@users.noreply.github.com`;\n } catch {\n this.botEmail = `${this.appSlug}[bot]@users.noreply.github.com`;\n }\n this.watchedRepos =\n this.config.repos.length > 0\n ? parseRepoList(this.config.repos)\n : (await this.client.listInstallationRepositories()).map((repository) => ({\n owner: repository.owner.login.toLowerCase(),\n repo: repository.name.toLowerCase(),\n }));\n if (this.watchedRepos.length === 0) {\n log.logWarning(\"GitHub: installation has no repositories; nothing to poll\");\n }\n\n // Restore persisted watermarks; a repo watched for the first time gets a\n // baseline of \"now\" so history never triggers (DESIGN.md § Event source).\n const persisted = this.loadSyncState();\n const now = new Date().toISOString();\n for (const repo of this.watchedRepos) {\n const repoKey = `${repo.owner}/${repo.repo}`;\n const saved = persisted?.repos[repoKey];\n this.repoState.set(\n repoKey,\n saved\n ? {\n baseline: saved.baseline,\n cursor: saved.cursor,\n seenComments: new Set(saved.seenComments),\n seenIssues: new Set(saved.seenIssues),\n seenReviewComments: new Set(saved.seenReviewComments ?? []),\n }\n : {\n baseline: now,\n cursor: now,\n seenComments: new Set(),\n seenIssues: new Set(),\n seenReviewComments: new Set(),\n },\n );\n }\n this.persistSyncState();\n\n setInterval(() => {\n void this.poll();\n }, this.config.pollIntervalMs).unref();\n\n log.logConnected(\"GitHub\");\n log.logInfo(\n `GitHub bot started as @${this.appSlug}[bot], polling ${this.watchedRepos.length} repo(s) every ${Math.round(this.config.pollIntervalMs / 1000)}s`,\n );\n }\n\n async postMessage(channel: string, text: string): Promise<string> {\n const ref = parseGithubConversationId(channel);\n const parts = splitText(text, GITHUB_MAX_COMMENT_LENGTH, formatGithubContinuation);\n const firstId = await this.postComment(ref, parts[0] ?? text);\n for (const part of parts.slice(1)) {\n await this.postComment(ref, part);\n }\n return String(firstId);\n }\n\n async updateMessage(channel: string, ts: string, text: string): Promise<void> {\n const ref = parseGithubConversationId(channel);\n await githubRetry(() => this.client.updateIssueComment(ref.owner, ref.repo, Number(ts), text));\n }\n\n async addReaction(channel: string, messageTs: string, emoji: string): Promise<void> {\n const ref = parseGithubConversationId(channel);\n const content = GITHUB_REACTIONS[emoji.replace(/^:|:$/g, \"\")];\n if (!content) {\n throw new Error(\n `GitHub does not support reaction '${emoji}' (supported: ${Object.keys(GITHUB_REACTIONS).join(\", \")})`,\n );\n }\n const reviewCommentId = parseReviewCommentTs(messageTs);\n await githubRetry(() => {\n if (messageTs === GITHUB_ISSUE_BODY_TS) {\n return this.client.createIssueReaction(ref.owner, ref.repo, ref.number, content);\n }\n if (reviewCommentId !== null) {\n return this.client.createReviewCommentReaction(\n ref.owner,\n ref.repo,\n reviewCommentId,\n content,\n );\n }\n return this.client.createCommentReaction(ref.owner, ref.repo, Number(messageTs), content);\n });\n }\n\n enqueueEvent(event: ConversationEvent): boolean {\n const conversationId = event.conversationId;\n const queue = this.getQueue(conversationId);\n if (queue.size() >= 5) {\n log.logWarning(\n `Event queue full for ${conversationId}, discarding: ${event.text.substring(0, 50)}`,\n );\n return false;\n }\n log.logInfo(`Enqueueing event for ${conversationId}: ${event.text.substring(0, 50)}`);\n queue.enqueue(() => {\n const context = createGithubAdapters(event as GithubEvent, this);\n return this.handler.handleEvent(event, this, context);\n });\n return true;\n }\n\n getMessagingInfo(): MessagingInfo {\n return {\n name: \"github\",\n trustModel: \"open-trigger\",\n formattingGuide:\n \"## GitHub Formatting (GitHub Flavored Markdown)\\n\" +\n \"Standard Markdown plus tables, task lists, fenced code blocks, and ```suggestion blocks.\\n\" +\n \"Reference issues/PRs as #123 and users as @login (mentions notify people — use sparingly).\",\n channels: [],\n users: [],\n };\n }\n\n // ==========================================================================\n // Internal helpers (used by context.ts)\n // ==========================================================================\n\n async postComment(ref: GithubConversationRef, text: string): Promise<number> {\n const comment = await githubRetry(() =>\n this.client.createIssueComment(ref.owner, ref.repo, ref.number, text),\n );\n return comment.id;\n }\n\n async deleteComment(ref: GithubConversationRef, commentId: number): Promise<void> {\n await githubRetry(() => this.client.deleteIssueComment(ref.owner, ref.repo, commentId));\n }\n\n logToFile(conversationId: string, entry: object): void {\n appendChannelLog(this.office(conversationId), entry);\n }\n\n logBotResponse(conversationId: string, text: string, ts: string): void {\n appendBotResponseLog(this.office(conversationId), text, ts);\n }\n\n // ==========================================================================\n // Private - polling\n // ==========================================================================\n\n private getQueue(conversationId: string): MessagingEventQueue {\n let queue = this.queues.get(conversationId);\n if (!queue) {\n queue = new MessagingEventQueue(\"GitHub\");\n this.queues.set(conversationId, queue);\n }\n return queue;\n }\n\n /**\n * Webhook poke: run a poll soon. Debounced so a burst of deliveries costs\n * one tick; a poke landing mid-poll marks it pending and the tick re-runs,\n * because the in-flight pass may already be past the poked repo's feeds.\n */\n requestPoll(debounceMs = REQUEST_POLL_DEBOUNCE_MS): void {\n if (this.pollInFlight) {\n this.pollPending = true;\n return;\n }\n if (this.requestPollTimer) return;\n this.requestPollTimer = setTimeout(() => {\n this.requestPollTimer = null;\n void this.poll();\n }, debounceMs);\n this.requestPollTimer.unref();\n }\n\n /** One poll tick over every watched repo. Public for tests. */\n async poll(): Promise<void> {\n if (this.pollInFlight) {\n this.pollPending = true;\n return;\n }\n this.pollInFlight = true;\n try {\n let changed = false;\n for (const repo of this.watchedRepos) {\n try {\n changed = (await this.pollRepo(repo)) || changed;\n } catch (err) {\n log.logWarning(\n `GitHub poll failed for ${repo.owner}/${repo.repo}`,\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n if (changed) {\n this.persistSyncState();\n }\n } finally {\n this.pollInFlight = false;\n if (this.pollPending) {\n this.pollPending = false;\n this.requestPoll();\n }\n }\n }\n\n private async pollRepo(repo: GithubRepoRef): Promise<boolean> {\n const repoKey = `${repo.owner}/${repo.repo}`;\n const state = this.repoState.get(repoKey);\n if (!state) return false;\n const since = new Date(Date.parse(state.cursor) - POLL_OVERLAP_MS).toISOString();\n let changed = false;\n\n // Comment activity also bumps the parent issue's updated_at, so the issues\n // list mostly echoes the comments list; only issues *created* since the\n // baseline are new conversations (their body is the first message).\n const issues = (await this.client.listIssuesSince(repo.owner, repo.repo, since)) ?? [];\n changed =\n (await this.advanceFeed(state, state.seenIssues, issues, (issue) => ({\n ref: { ...repo, number: issue.number },\n ts: GITHUB_ISSUE_BODY_TS,\n user: issue.user.login,\n text: `# ${issue.title}\\n\\n${issue.body ?? \"\"}`.trim(),\n createdAt: issue.created_at,\n isPr: Boolean(issue.pull_request),\n }))) || changed;\n\n const comments = (await this.client.listIssueCommentsSince(repo.owner, repo.repo, since)) ?? [];\n changed =\n (await this.advanceFeed(state, state.seenComments, comments, (comment) => ({\n ref: { ...repo, number: issueNumberFromUrl(comment.issue_url) },\n ts: String(comment.id),\n user: comment.user.login,\n text: comment.body,\n createdAt: comment.created_at,\n }))) || changed;\n\n // Inline PR review comments live in their own endpoint and id space; the\n // same watermark discipline applies. The bot's own thread replies (the\n // github_review_reply tool) re-surface here and are dropped as Bot-authored.\n const reviewComments =\n (await this.client.listPullReviewCommentsSince(repo.owner, repo.repo, since)) ?? [];\n changed =\n (await this.advanceFeed(state, state.seenReviewComments, reviewComments, (comment) => ({\n ref: { ...repo, number: prNumberFromUrl(comment.pull_request_url) },\n ts: githubReviewCommentTs(comment.id),\n user: comment.user.login,\n text: comment.body,\n createdAt: comment.created_at,\n isPr: true,\n review: {\n commentId: comment.id,\n path: comment.path,\n line: comment.line,\n diffHunk: comment.diff_hunk,\n inReplyToId: comment.in_reply_to_id,\n },\n }))) || changed;\n\n pruneSeen(state.seenComments);\n pruneSeen(state.seenIssues);\n pruneSeen(state.seenReviewComments);\n return changed;\n }\n\n /**\n * One feed's watermark advance — the same discipline for all three feeds:\n * bump the cursor on any fresher updated_at, then let the id watermark plus\n * the creation baseline decide what actually triggers (edits re-surface old\n * items with a fresh updated_at). Bot-authored items advance the watermark\n * without triggering.\n */\n private async advanceFeed<\n T extends {\n id: number;\n created_at: string;\n updated_at: string;\n user: { login: string; type: string };\n },\n >(\n state: RepoWatermark,\n seen: Set<number>,\n items: T[],\n toIncoming: (item: T) => IncomingItem,\n ): Promise<boolean> {\n let changed = false;\n for (const item of items) {\n if (item.updated_at > state.cursor) {\n state.cursor = item.updated_at;\n changed = true;\n }\n if (item.created_at < state.baseline || seen.has(item.id)) continue;\n seen.add(item.id);\n changed = true;\n if (item.user.type === \"Bot\") continue;\n await this.handleIncoming(toIncoming(item));\n }\n return changed;\n }\n\n // ==========================================================================\n // Private - watermark persistence\n // ==========================================================================\n\n private loadSyncState(): GithubSyncState | undefined {\n try {\n return readJsonSchemaFileIfExists(\n this.config.syncStatePath,\n SyncStateSchema,\n (detail) => `Malformed GitHub sync state at ${this.config.syncStatePath}: ${detail}`,\n );\n } catch (err) {\n // A bad state file re-baselines (history won't trigger) rather than\n // blocking startup; the next persist overwrites it.\n log.logWarning(\n \"GitHub: ignoring unreadable sync state\",\n err instanceof Error ? err.message : String(err),\n );\n return undefined;\n }\n }\n\n /** The persisted form of the current watermarks; the test/inspection surface. */\n syncStateSnapshot(): GithubSyncState {\n const state: GithubSyncState = { repos: {} };\n for (const [repoKey, watermark] of this.repoState) {\n state.repos[repoKey] = {\n baseline: watermark.baseline,\n cursor: watermark.cursor,\n seenComments: [...watermark.seenComments],\n seenIssues: [...watermark.seenIssues],\n seenReviewComments: [...watermark.seenReviewComments],\n };\n }\n return state;\n }\n\n private persistSyncState(): void {\n ensureDirExists(dirname(this.config.syncStatePath));\n atomicWritePrivateFile(this.config.syncStatePath, JSON.stringify(this.syncStateSnapshot()));\n }\n\n // ==========================================================================\n // Private - triggering\n // ==========================================================================\n\n /** Fresh regex per call: the `g` flag makes `test`/`replace` stateful. */\n private mentionPattern(): RegExp | null {\n return this.appSlug ? new RegExp(`@${this.appSlug}(?![\\\\w-])`, \"gi\") : null;\n }\n\n private isMentioned(text: string): boolean {\n const pattern = this.mentionPattern();\n return pattern ? pattern.test(text) : false;\n }\n\n private stripMention(text: string): string {\n const pattern = this.mentionPattern();\n return (pattern ? text.replace(pattern, \"\") : text).trim();\n }\n\n /** The Conversation office for a GitHub conversation id (one PR/issue). */\n private office(conversationId: string): Office {\n return this.config.workspace.office(createOfficeAddress(\"github\", conversationId));\n }\n\n private isParticipating(conversationId: string): boolean {\n return existsSync(this.office(conversationId).logPath);\n }\n\n /**\n * True when `user` holds at least write permission on the repo. Fails\n * closed: a failed lookup denies the trigger (and logs) rather than\n * letting an unverified commenter drive the agent.\n */\n private async hasTriggerPermission(ref: GithubConversationRef, user: string): Promise<boolean> {\n const cacheKey = `${ref.owner}/${ref.repo}#${user}`;\n const cached = this.permissionCache.get(cacheKey);\n if (cached && Date.now() < cached.expiresAt) {\n return cached.rank >= REQUIRED_TRIGGER_RANK;\n }\n let rank: number;\n try {\n const role = await githubRetry(() =>\n this.client.getCollaboratorPermission(ref.owner, ref.repo, user),\n );\n // Custom role_name values are unrankable; the legacy permission field\n // still carries their closest standard mapping, so take the stronger.\n rank = Math.max(rankOfPermission(role.role_name ?? \"\"), rankOfPermission(role.permission));\n } catch (err) {\n log.logWarning(\n `GitHub: permission lookup failed for ${user} on ${ref.owner}/${ref.repo}; denying trigger`,\n err instanceof Error ? err.message : String(err),\n );\n return false;\n }\n this.permissionCache.set(cacheKey, {\n rank,\n expiresAt: Date.now() + PERMISSION_CACHE_TTL_MS,\n });\n return rank >= REQUIRED_TRIGGER_RANK;\n }\n\n private async handleIncoming(item: IncomingItem): Promise<void> {\n const conversationId = buildGithubConversationId(item.ref);\n const mentioned = this.isMentioned(item.text);\n const participating = this.isParticipating(conversationId);\n // Narrow trigger (DESIGN.md): only threads the bot is mentioned in or\n // already participates in. Everything else is ignored without logging so\n // busy repos don't grow conversation dirs for untouched issues.\n if (!mentioned && !participating) return;\n\n // Permission gate: on public repos anyone can comment, so a mention from\n // anyone below write permission is ignored entirely (no log, no state).\n if (!(await this.hasTriggerPermission(item.ref, item.user))) {\n log.logInfo(\n `GitHub: ignoring ${conversationId} comment from ${item.user} (below write permission)`,\n );\n return;\n }\n\n const cleanedText = this.stripMention(item.text);\n const sessionKey = resolveChatSessionKey({\n conversationId,\n conversationKind: \"shared\",\n messageId: item.ts,\n persistentTopLevel: true,\n });\n\n const messageText = item.review\n ? await this.formatReviewMessage(item, cleanedText)\n : cleanedText;\n\n const eventBase = createConversationEvent({\n platform: \"github\",\n type: item.ts === GITHUB_ISSUE_BODY_TS ? \"issue\" : \"message\",\n conversationId,\n conversationKind: \"shared\",\n ts: item.ts,\n sessionKey,\n user: item.user,\n userName: item.user,\n text: messageText,\n }) as GithubEvent;\n\n await processMessageIntake({\n eventBase,\n office: this.office(eventBase.conversationId),\n isAutoReplyCandidate: false,\n // Match on the user-typed text, not the review-decorated messageText.\n magicWord: { text: cleanedText, addressed: mentioned, scopeFallback: \"never\" },\n busyPolicy: \"queue\",\n logEntryBase: {\n date: item.createdAt,\n ts: item.ts,\n user: item.user,\n userName: item.user,\n text: messageText,\n isMessagingBot: false,\n },\n // log.jsonl existence is the participation authority for this adapter:\n // a first-contact magic word (\"@bot stop\" on an untouched issue) must\n // not materialize the log, or every later comment from any writer\n // would be treated as addressed to a conversation the bot never joined.\n log: (entry) => {\n if (!participating && matchMagicWord(cleanedText) === \"stop\") return;\n this.logToFile(conversationId, entry);\n },\n // GitHub has no attachments; the prep hook is used to lay down the\n // issue context and repo clone only for messages that will dispatch,\n // and before the comment itself is logged.\n processAttachments: async () => {\n await this.prepareConversation(item, conversationId, participating);\n return [];\n },\n queueKey: conversationId,\n enqueue: (queueKey, work) => this.getQueue(queueKey).enqueue(work),\n handler: this.handler,\n bot: this,\n createContext: (event) => createGithubAdapters(event, this),\n });\n }\n\n /**\n * First contact: log the issue title/body ahead of the comment so the\n * session history starts with what the thread is about. The clone is\n * (re)attempted on every trigger while ./repo is missing — a no-op once\n * it exists — so a failed first clone (e.g. App permissions granted\n * later) heals on the next mention instead of wedging the conversation.\n */\n private async prepareConversation(\n item: IncomingItem,\n conversationId: string,\n participating: boolean,\n ): Promise<void> {\n let isPrHint = item.isPr;\n if (!participating && item.ts !== GITHUB_ISSUE_BODY_TS) {\n const issue = await this.logIssueContext(item.ref, conversationId, item.createdAt);\n // Only comments arrive without the PR-ness hint; review comments carry\n // isPr: true (they only exist on PRs) and that knowledge is authoritative.\n if (issue && isPrHint === undefined) isPrHint = Boolean(issue.pull_request);\n }\n if (!existsSync(conversationRepoDir(this.office(conversationId)))) {\n const isPr = isPrHint ?? (await fetchIsPr(this.client, item.ref));\n await this.ensureRepoClone(item.ref, conversationId, isPr);\n }\n }\n\n /**\n * Decorates an inline review comment with its diff anchor and (for replies)\n * the thread's earlier turns, so the agent knows which code the feedback is\n * about without hunting through the PR. The rc-<id> in the header is what\n * github_review_reply takes to answer in-thread.\n */\n private async formatReviewMessage(item: IncomingItem, cleanedText: string): Promise<string> {\n const review = item.review!;\n const location = review.line !== null ? `${review.path}:${review.line}` : review.path;\n const parts = [`[PR review comment ${githubReviewCommentTs(review.commentId)} on ${location}]`];\n if (review.diffHunk) {\n const hunk =\n review.diffHunk.length > MAX_DIFF_HUNK_CHARS\n ? `…${review.diffHunk.slice(-MAX_DIFF_HUNK_CHARS)}`\n : review.diffHunk;\n parts.push(`\\`\\`\\`diff\\n${hunk}\\n\\`\\`\\``);\n }\n if (review.inReplyToId !== undefined) {\n const turns = await this.reviewThreadContext(item.ref, review.inReplyToId, review.commentId);\n if (turns.length > 0) {\n parts.push(`Thread so far:\\n${turns.join(\"\\n\")}`);\n }\n }\n parts.push(cleanedText);\n return parts.join(\"\\n\");\n }\n\n /**\n * Earlier turns of one review thread (root + replies before the trigger),\n * newest-truncated. Fail-soft: context is a nicety, the trigger is not.\n */\n private async reviewThreadContext(\n ref: GithubConversationRef,\n rootId: number,\n beforeId: number,\n ): Promise<string[]> {\n try {\n const all = await githubRetry(() =>\n this.client.listPullReviewComments(ref.owner, ref.repo, ref.number),\n );\n return all\n .filter(\n (comment) =>\n (comment.id === rootId || comment.in_reply_to_id === rootId) && comment.id < beforeId,\n )\n .slice(-MAX_THREAD_TURNS)\n .map((comment) => {\n const body =\n comment.body.length > MAX_THREAD_TURN_CHARS\n ? `${comment.body.slice(0, MAX_THREAD_TURN_CHARS)}…`\n : comment.body;\n return `@${comment.user.login}: ${body}`;\n });\n } catch (err) {\n log.logWarning(\n `GitHub: could not fetch review thread context for ${ref.owner}/${ref.repo}#${ref.number}`,\n err instanceof Error ? err.message : String(err),\n );\n return [];\n }\n }\n\n private async logIssueContext(\n ref: GithubConversationRef,\n conversationId: string,\n triggerCreatedAt: string,\n ): Promise<GithubIssue | null> {\n let issue: GithubIssue;\n try {\n issue = await githubRetry(() => this.client.getIssue(ref.owner, ref.repo, ref.number));\n } catch (err) {\n log.logWarning(\n `GitHub: could not fetch issue context for ${conversationId}`,\n err instanceof Error ? err.message : String(err),\n );\n return null;\n }\n // Dated just before the triggering comment, NOT issue.created_at: history\n // sync date-sorts entries and drops anything older than its recency\n // window, so an old issue's real creation date would silently evict the\n // one message that says what the thread is about.\n const triggerMs = Date.parse(triggerCreatedAt);\n const contextDate = new Date((Number.isFinite(triggerMs) ? triggerMs : Date.now()) - 1000);\n this.logToFile(conversationId, {\n date: contextDate.toISOString(),\n ts: GITHUB_ISSUE_BODY_TS,\n user: issue.user.login,\n userName: issue.user.login,\n text: `# ${issue.title}\\n\\n${issue.body ?? \"\"}`.trim(),\n attachments: [],\n isMessagingBot: false,\n });\n return issue;\n }\n\n // ==========================================================================\n // Repo clone\n // ==========================================================================\n\n /**\n * Clone the conversation's repo into its dir (bind-mounted into the\n * sandbox) using an ephemeral contents:read token that never leaves the\n * host. Non-fatal: a failed clone degrades to the pre-clone experience.\n */\n private async ensureRepoClone(\n ref: GithubConversationRef,\n conversationId: string,\n isPr: boolean,\n ): Promise<void> {\n const office = this.office(conversationId);\n const dir = conversationRepoDir(office);\n if (existsSync(dir)) return;\n try {\n office.ensure();\n const token = await this.client.createScopedInstallationToken(ref.repo, {\n contents: \"read\",\n });\n const prHeadBranch = isPr ? await fetchPrHeadBranch(this.client, ref) : undefined;\n await cloneRepo({\n url: `https://github.com/${ref.owner}/${ref.repo}.git`,\n dir,\n token,\n botLogin: `${this.appSlug}[bot]`,\n botEmail: this.botEmail ?? `${this.appSlug}[bot]@users.noreply.github.com`,\n prNumber: isPr ? ref.number : undefined,\n prHeadBranch,\n });\n log.logInfo(\n `[${conversationId}] Cloned ${ref.owner}/${ref.repo}${isPr ? ` and checked out PR #${ref.number} head as ${prHeadBranch ?? `pr-${ref.number}`}` : \"\"}`,\n );\n } catch (err) {\n log.logWarning(\n `GitHub: repo clone failed for ${conversationId}`,\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n}\n"]}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { type ConversationMessage } from "../../adapter.js";
|
|
1
|
+
import { type ConversationContext } from "../../adapter.js";
|
|
3
2
|
import { type GithubMessagingBot } from "./bot.js";
|
|
4
3
|
import type { GithubEvent } from "./types.js";
|
|
5
|
-
|
|
6
|
-
export declare function createGithubAdapters(event: GithubEvent, bot: GithubMessagingBot): {
|
|
7
|
-
address: OfficeAddress;
|
|
8
|
-
message: ConversationMessage;
|
|
9
|
-
responder: ConversationResponder;
|
|
10
|
-
platform: MessagingInfo;
|
|
11
|
-
};
|
|
4
|
+
export declare function createGithubAdapters(event: GithubEvent, bot: GithubMessagingBot): ConversationContext;
|
|
12
5
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/adapters/github/context.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/adapters/github/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAGvF,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAG7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,kBAAkB,GACtB,mBAAmB,CAmGrB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/adapters/github/context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/adapters/github/context.ts"],"names":[],"mappings":"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","sourcesContent":["import { createConversationMessage, type ConversationContext } from \"../../adapter.js\";\nimport { resolveChatSessionKey } from \"../../sessions/session-key.js\";\nimport { createProgressiveRenderer, formatMarkdownToolResult } from \"../progressive-renderer.js\";\nimport { formatGithubContinuation, type GithubMessagingBot } from \"./bot.js\";\nimport { GITHUB_MAX_COMMENT_LENGTH } from \"./client.js\";\nimport { parseGithubConversationId } from \"./ids.js\";\nimport type { GithubEvent } from \"./types.js\";\n\nexport function createGithubAdapters(\n event: GithubEvent,\n bot: GithubMessagingBot,\n): ConversationContext {\n const conversationId = event.conversationId;\n const ref = parseGithubConversationId(conversationId);\n\n const message = createConversationMessage({\n platform: \"github\",\n conversationId,\n address: event.address,\n id: event.ts,\n sessionKey:\n event.sessionKey ??\n resolveChatSessionKey({\n conversationId,\n conversationKind: event.conversationKind,\n messageId: event.ts,\n persistentTopLevel: true,\n threadTs: event.thread_ts,\n }),\n conversationKind: event.conversationKind,\n userId: event.user,\n userName: event.userName,\n text: event.text,\n attachments: event.attachments,\n threadTs: event.thread_ts,\n });\n // the conversation-scoped context below is an explicit append, not a fork.\n const baseInfo = bot.getMessagingInfo();\n const platform = {\n ...baseInfo,\n formattingGuide:\n `${baseInfo.formattingGuide}\\n\\n` +\n `## Conversation context\\n` +\n `This conversation IS GitHub issue/PR ${ref.owner}/${ref.repo}#${ref.number}: the ` +\n `first message in the history is its title and body, and the following messages are ` +\n `its comments. When the user says \"this issue\", they mean #${ref.number}. Messages ` +\n `tagged [PR review comment rc-<id> …] are inline review threads on a diff line: ` +\n `answer those with the github_review_reply tool (comment_id = that id) so the reply ` +\n `lands in-thread — your normal response posts as a plain PR comment.\\n\\n` +\n `## Repository & pull requests\\n` +\n `The repository is cloned at ./repo — a snapshot from this conversation's first ` +\n `trigger; run github_sync when it may be stale to pull the latest PR head or base ` +\n `branch. If this conversation is a pull request, its head branch is checked out ` +\n `under its real name (run git branch --show-current in ./repo to see it; fork PRs ` +\n `fall back to pr-${ref.number}). You have no git credentials, so git fetch/push ` +\n `fail by design.\\n` +\n `To ship code changes: commit inside ./repo (the git author is preconfigured) on a ` +\n `pi/<name> branch, then call the github_pr tool to push it. When this conversation's ` +\n `checked-out PR head branch is already named pi/<name> — e.g. a PR you opened ` +\n `earlier — commit directly on it and pass that branch to github_pr: the push ` +\n `updates THIS pull request instead of opening a new one. Any other branch opens a ` +\n `new pull request (draft: true for a draft); calling github_pr again with the same ` +\n `branch pushes new commits to its existing PR. Use github_checks to read CI results ` +\n `for your branch (or this PR) — pass a failing check's job id to read its log — and ` +\n `iterate until they pass. You cannot push the default branch or ` +\n `merge — humans review and merge every PR.\\n` +\n `github_read looks up PR/issue metadata this clone cannot show (diff stats, changed ` +\n `files, review state, other issues in this repo); github_issue manages labels, ` +\n `assignees, and close/reopen for triage.`,\n diagnostics: {\n showUsageSummary: false,\n },\n };\n\n // streaming: false — GitHub gets the finished response in one comment.\n // Streaming would edit the comment on every flush: API churn and \"edited\"\n // noise for readers who refresh rather than watch typing. There is also no\n // typing indicator or working suffix; progress shows through comment edits.\n const { responder } = createProgressiveRenderer({\n label: \"GitHub\",\n maxLength: GITHUB_MAX_COMMENT_LENGTH,\n formatContinuation: formatGithubContinuation,\n errorPrefix: \"**Error:** \",\n formatToolResult: formatMarkdownToolResult,\n logIntermediateResponses: true,\n responseErrorContext: (responseId) => ({\n platform: \"github\",\n conversationId,\n messageId: message.id,\n sessionKey: message.sessionKey,\n responseMessageId: responseId === null ? null : Number(responseId),\n conversationKind: message.conversationKind,\n }),\n post: async (text) => {\n return String(await bot.postComment(ref, text));\n },\n update: (id, text) => bot.updateMessage(conversationId, id, text),\n postExtra: async (text) => bot.postComment(ref, text),\n delete: async (id) => {\n await bot.deleteComment(ref, Number(id));\n },\n logBotResponse: (text, id) => bot.logBotResponse(conversationId, text, id),\n // The REST API cannot attach files to comments (uploads are a browser\n // feature); leave a pointer instead of failing the run.\n uploadFallbackNote: (name) =>\n `*(file \\`${name}\\` was produced, but the GitHub adapter cannot attach files to comments)*`,\n react: (emoji) => bot.addReaction(conversationId, event.ts, emoji),\n });\n\n return { address: message.address, message, responder, platform };\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { GithubClient } from "./client.js";
|
|
2
2
|
import type { Workspace } from "../../office/index.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { GithubCheckSummary, GithubConversationRef, GithubIssueRequest, GithubPrRequest, GithubPrResult, GithubReadRequest, GithubReadResult, PlatformGithubOps } from "./types.js";
|
|
4
4
|
/** Whether the conversation's issue is a PR, for callers where the triggering
|
|
5
5
|
* item didn't carry that knowledge. Errs toward plain issue. */
|
|
6
6
|
export declare function fetchIsPr(client: GithubClient, ref: GithubConversationRef): Promise<boolean>;
|
|
@@ -15,18 +15,15 @@ export declare function fetchPrHeadBranch(client: GithubClient, ref: GithubConve
|
|
|
15
15
|
/**
|
|
16
16
|
* Host-side backend of the github_* tool pack (`PlatformGithubOps`),
|
|
17
17
|
* standalone from the messaging bot: it needs the API client, the
|
|
18
|
-
* conversation working dir
|
|
18
|
+
* conversation working dir — not the poll
|
|
19
19
|
* loop, queues, or trigger gate. Tokens are minted per call, scoped to the
|
|
20
20
|
* conversation's repo, and never enter the sandbox.
|
|
21
21
|
*/
|
|
22
22
|
export declare class GithubOps implements PlatformGithubOps {
|
|
23
23
|
private readonly client;
|
|
24
24
|
private readonly config;
|
|
25
|
-
/** Cloud Build ids seen in getChecks summaries → their GCP project. */
|
|
26
|
-
private buildRef;
|
|
27
25
|
constructor(client: GithubClient, config: {
|
|
28
26
|
workspace: Workspace;
|
|
29
|
-
cloudBuild?: GithubBotConfig["cloudBuild"];
|
|
30
27
|
});
|
|
31
28
|
private repoDir;
|
|
32
29
|
/**
|
|
@@ -41,15 +38,6 @@ export declare class GithubOps implements PlatformGithubOps {
|
|
|
41
38
|
* pushed, or for the conversation's PR head when no branch is given.
|
|
42
39
|
*/
|
|
43
40
|
getChecks(conversationId: string, branch?: string): Promise<GithubCheckSummary[]>;
|
|
44
|
-
private rememberBuild;
|
|
45
|
-
/**
|
|
46
|
-
* Backs the Cloud Build log mode of `github_checks`. GCP credentials stay
|
|
47
|
-
* host-side (ADC via GOOGLE_APPLICATION_CREDENTIALS — e.g. a Workload
|
|
48
|
-
* Identity Federation external_account file); the build must have appeared
|
|
49
|
-
* in a github_checks summary first, which is also where its project is
|
|
50
|
-
* learned. Unreadable logs degrade to the console url, never a dead end.
|
|
51
|
-
*/
|
|
52
|
-
getBuildLog(conversationId: string, buildId: string): Promise<string>;
|
|
53
41
|
/**
|
|
54
42
|
* Backs the `github_sync` tool: refresh the conversation's ./repo clone
|
|
55
43
|
* from origin with an ephemeral read token. Fetch-only when moving the
|
|
@@ -82,9 +70,8 @@ export declare class GithubOps implements PlatformGithubOps {
|
|
|
82
70
|
/**
|
|
83
71
|
* Backs the log mode of `github_checks`: the tail of one CI job's log so
|
|
84
72
|
* the agent can diagnose a failing check without sandbox credentials. Only
|
|
85
|
-
* GitHub Actions checks have logs on GitHub
|
|
86
|
-
*
|
|
87
|
-
* into guidance instead of a dead end.
|
|
73
|
+
* GitHub Actions checks have logs on GitHub; external CI apps keep theirs
|
|
74
|
+
* on their own service, so a 404 here becomes guidance instead of a dead end.
|
|
88
75
|
*/
|
|
89
76
|
getJobLog(conversationId: string, jobId: number): Promise<string>;
|
|
90
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-ops.d.ts","sourceRoot":"","sources":["../../../src/adapters/github/github-ops.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"github-ops.d.ts","sourceRoot":"","sources":["../../../src/adapters/github/github-ops.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKhD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAKpB;iEACiE;AACjE,wBAAsB,SAAS,CAC7B,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,qBAAqB,GACzB,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,qBAAqB,GACzB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAS7B;AAED;;;;;;GAMG;AACH,qBAAa,SAAU,YAAW,iBAAiB;IAE/C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFzB,YACmB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE;QAAE,SAAS,EAAE,SAAS,CAAA;KAAE,EAC/C;IAEJ,OAAO,CAAC,OAAO;IAMf;;;;;OAKG;IACG,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAqD/F;IAED;;;OAGG;IACG,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CA2BtF;IAED;;;;;OAKG;IACG,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyCvE;IAED;;;;OAIG;IACG,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4C9F;IAED;;;;;OAKG;IACG,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoEtF;IAED;;;;;OAKG;IACG,mBAAmB,CACvB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CA4B1B;IAED;;;;;OAKG;IACG,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBtE;CACF"}
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import * as log from "../../log.js";
|
|
3
3
|
import { GithubApiError, GITHUB_MAX_COMMENT_LENGTH, githubRetry } from "./client.js";
|
|
4
|
-
import { CLOUD_BUILD_APP_SLUG, CloudBuildLogUnavailableError, fetchCloudBuildLog, isCloudBuildId, projectFromDetailsUrl, } from "./cloudbuild.js";
|
|
5
4
|
import { parseGithubConversationId } from "./ids.js";
|
|
6
5
|
import { conversationRepoDir, GITHUB_PUSH_BRANCH_PATTERN, pushBranch, syncRepo } from "./repo.js";
|
|
7
6
|
import { createOfficeAddress } from "../../office/index.js";
|
|
8
|
-
/**
|
|
7
|
+
/** CI job logs are tail-truncated to this many characters. */
|
|
9
8
|
const MAX_LOG_CHARS = 20000;
|
|
10
|
-
function truncateLogTail(logText) {
|
|
11
|
-
return logText.length > MAX_LOG_CHARS
|
|
12
|
-
? `…(truncated to the last ${MAX_LOG_CHARS} chars)\n${logText.slice(-MAX_LOG_CHARS)}`
|
|
13
|
-
: logText;
|
|
14
|
-
}
|
|
15
9
|
/** Whether the conversation's issue is a PR, for callers where the triggering
|
|
16
10
|
* item didn't carry that knowledge. Errs toward plain issue. */
|
|
17
11
|
export async function fetchIsPr(client, ref) {
|
|
@@ -43,7 +37,7 @@ export async function fetchPrHeadBranch(client, ref) {
|
|
|
43
37
|
/**
|
|
44
38
|
* Host-side backend of the github_* tool pack (`PlatformGithubOps`),
|
|
45
39
|
* standalone from the messaging bot: it needs the API client, the
|
|
46
|
-
* conversation working dir
|
|
40
|
+
* conversation working dir — not the poll
|
|
47
41
|
* loop, queues, or trigger gate. Tokens are minted per call, scoped to the
|
|
48
42
|
* conversation's repo, and never enter the sandbox.
|
|
49
43
|
*/
|
|
@@ -51,8 +45,6 @@ export class GithubOps {
|
|
|
51
45
|
constructor(client, config) {
|
|
52
46
|
this.client = client;
|
|
53
47
|
this.config = config;
|
|
54
|
-
/** Cloud Build ids seen in getChecks summaries → their GCP project. */
|
|
55
|
-
this.buildRef = new Map();
|
|
56
48
|
}
|
|
57
49
|
repoDir(conversationId) {
|
|
58
50
|
return conversationRepoDir(this.config.workspace.office(createOfficeAddress("github", conversationId)));
|
|
@@ -127,77 +119,15 @@ export class GithubOps {
|
|
|
127
119
|
target = pr.head.sha;
|
|
128
120
|
}
|
|
129
121
|
const runs = await githubRetry(() => this.client.listCheckRuns(ref.owner, ref.repo, target));
|
|
130
|
-
return runs.map((run) => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
isCloudBuildId(externalId)) {
|
|
140
|
-
const project = projectFromDetailsUrl(run.details_url) ?? this.config.cloudBuild.projectFallback;
|
|
141
|
-
if (project) {
|
|
142
|
-
this.rememberBuild(externalId, project);
|
|
143
|
-
buildLogAvailable = true;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return {
|
|
147
|
-
id: run.id,
|
|
148
|
-
name: run.name,
|
|
149
|
-
status: run.status,
|
|
150
|
-
conclusion: run.conclusion,
|
|
151
|
-
url: run.html_url,
|
|
152
|
-
appSlug: run.app?.slug ?? null,
|
|
153
|
-
outputSummary: run.output?.summary?.trim() ? run.output.summary.slice(0, 500) : null,
|
|
154
|
-
externalId,
|
|
155
|
-
buildLogAvailable,
|
|
156
|
-
};
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
rememberBuild(buildId, project) {
|
|
160
|
-
// Insertion-ordered Map as a small LRU: re-insert on touch, prune oldest.
|
|
161
|
-
this.buildRef.delete(buildId);
|
|
162
|
-
this.buildRef.set(buildId, { project });
|
|
163
|
-
if (this.buildRef.size > 200) {
|
|
164
|
-
const oldest = this.buildRef.keys().next().value;
|
|
165
|
-
if (oldest !== undefined)
|
|
166
|
-
this.buildRef.delete(oldest);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Backs the Cloud Build log mode of `github_checks`. GCP credentials stay
|
|
171
|
-
* host-side (ADC via GOOGLE_APPLICATION_CREDENTIALS — e.g. a Workload
|
|
172
|
-
* Identity Federation external_account file); the build must have appeared
|
|
173
|
-
* in a github_checks summary first, which is also where its project is
|
|
174
|
-
* learned. Unreadable logs degrade to the console url, never a dead end.
|
|
175
|
-
*/
|
|
176
|
-
async getBuildLog(conversationId, buildId) {
|
|
177
|
-
if (!this.config.cloudBuild) {
|
|
178
|
-
throw new Error("Cloud Build log access is not configured on this host (no GCP credentials).");
|
|
179
|
-
}
|
|
180
|
-
const known = this.buildRef.get(buildId);
|
|
181
|
-
if (!known) {
|
|
182
|
-
throw new Error(`Unknown build id ${buildId}: run github_checks first and take a [build …] id from ` +
|
|
183
|
-
`the summary.`);
|
|
184
|
-
}
|
|
185
|
-
let logText;
|
|
186
|
-
try {
|
|
187
|
-
logText = await fetchCloudBuildLog({
|
|
188
|
-
tokenProvider: this.config.cloudBuild.tokenProvider,
|
|
189
|
-
project: known.project,
|
|
190
|
-
buildId,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
catch (err) {
|
|
194
|
-
if (err instanceof CloudBuildLogUnavailableError) {
|
|
195
|
-
throw new Error(`${err.message}${err.consoleUrl ? ` Console: ${err.consoleUrl}` : ""} Use the check's ` +
|
|
196
|
-
`summary/url from github_checks, or reproduce the failure locally in ./repo.`, { cause: err });
|
|
197
|
-
}
|
|
198
|
-
throw err;
|
|
199
|
-
}
|
|
200
|
-
return truncateLogTail(logText);
|
|
122
|
+
return runs.map((run) => ({
|
|
123
|
+
id: run.id,
|
|
124
|
+
name: run.name,
|
|
125
|
+
status: run.status,
|
|
126
|
+
conclusion: run.conclusion,
|
|
127
|
+
url: run.html_url,
|
|
128
|
+
appSlug: run.app?.slug ?? null,
|
|
129
|
+
outputSummary: run.output?.summary?.trim() ? run.output.summary.slice(0, 500) : null,
|
|
130
|
+
}));
|
|
201
131
|
}
|
|
202
132
|
/**
|
|
203
133
|
* Backs the `github_sync` tool: refresh the conversation's ./repo clone
|
|
@@ -378,9 +308,8 @@ export class GithubOps {
|
|
|
378
308
|
/**
|
|
379
309
|
* Backs the log mode of `github_checks`: the tail of one CI job's log so
|
|
380
310
|
* the agent can diagnose a failing check without sandbox credentials. Only
|
|
381
|
-
* GitHub Actions checks have logs on GitHub
|
|
382
|
-
*
|
|
383
|
-
* into guidance instead of a dead end.
|
|
311
|
+
* GitHub Actions checks have logs on GitHub; external CI apps keep theirs
|
|
312
|
+
* on their own service, so a 404 here becomes guidance instead of a dead end.
|
|
384
313
|
*/
|
|
385
314
|
async getJobLog(conversationId, jobId) {
|
|
386
315
|
if (!Number.isInteger(jobId) || jobId <= 0) {
|
|
@@ -394,13 +323,15 @@ export class GithubOps {
|
|
|
394
323
|
catch (err) {
|
|
395
324
|
if (err instanceof GithubApiError && err.status === 404) {
|
|
396
325
|
throw new Error(`No GitHub Actions log for job ${jobId}. Logs are only available for checks reported ` +
|
|
397
|
-
`by github-actions; external CI
|
|
326
|
+
`by github-actions; external CI keeps logs on its own service — ` +
|
|
398
327
|
`use that check's summary/url from github_checks, or reproduce the failure locally ` +
|
|
399
328
|
`in ./repo instead. Do not retry with other ids.`, { cause: err });
|
|
400
329
|
}
|
|
401
330
|
throw err;
|
|
402
331
|
}
|
|
403
|
-
return
|
|
332
|
+
return logText.length > MAX_LOG_CHARS
|
|
333
|
+
? `…(truncated to the last ${MAX_LOG_CHARS} chars)\n${logText.slice(-MAX_LOG_CHARS)}`
|
|
334
|
+
: logText;
|
|
404
335
|
}
|
|
405
336
|
}
|
|
406
337
|
//# sourceMappingURL=github-ops.js.map
|