@agentwhy/cli 0.0.0-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +181 -0
- package/THIRD_PARTY_NOTICES.md +31 -0
- package/dist/adapter/claude-code/contract/assumptions.js +208 -0
- package/dist/adapter/claude-code/contract/denials.js +15 -0
- package/dist/adapter/claude-code/contract/entry-points.js +15 -0
- package/dist/adapter/claude-code/contract/fields.js +73 -0
- package/dist/adapter/claude-code/contract/hooks.js +96 -0
- package/dist/adapter/claude-code/contract/identifiers.js +15 -0
- package/dist/adapter/claude-code/contract/layout.js +29 -0
- package/dist/adapter/claude-code/contract/line-types.js +26 -0
- package/dist/adapter/claude-code/contract/projects.js +23 -0
- package/dist/adapter/claude-code/contract/recognition.js +14 -0
- package/dist/adapter/claude-code/contract/session-title.js +20 -0
- package/dist/adapter/claude-code/contract/settings.js +27 -0
- package/dist/adapter/claude-code/contract/task-notifications.js +33 -0
- package/dist/adapter/claude-code/contract/tools.js +37 -0
- package/dist/adapter/claude-code/contract/version.js +51 -0
- package/dist/adapter/claude-code/discovery/claude-code-project-catalogue.js +129 -0
- package/dist/adapter/claude-code/discovery/claude-code-recognition.js +46 -0
- package/dist/adapter/claude-code/discovery/claude-code-session-catalogue.js +100 -0
- package/dist/adapter/claude-code/discovery/claude-code-session-discovery.js +61 -0
- package/dist/adapter/claude-code/discovery/claude-code-session-titles.js +28 -0
- package/dist/adapter/claude-code/discovery/discovered-session.js +1 -0
- package/dist/adapter/claude-code/discovery/session-entries.js +41 -0
- package/dist/adapter/claude-code/discovery/transcript-tail.js +81 -0
- package/dist/adapter/claude-code/events/claude-code-session-source.js +197 -0
- package/dist/adapter/claude-code/events/delegation-index.js +15 -0
- package/dist/adapter/claude-code/events/transcript-scan.js +179 -0
- package/dist/adapter/claude-code/hooks/hook-output.js +42 -0
- package/dist/adapter/claude-code/hooks/pre-tool-use-input.js +23 -0
- package/dist/adapter/claude-code/hooks/stop-input.js +25 -0
- package/dist/adapter/claude-code/hooks/subagent-stop-input.js +26 -0
- package/dist/adapter/claude-code/policy/deny-rules.js +46 -0
- package/dist/adapter/claude-code/probe/claude-code-probe.js +86 -0
- package/dist/adapter/claude-code/probe/collectors/agent-tool-input-key-collector.js +24 -0
- package/dist/adapter/claude-code/probe/collectors/denial-kind-collector.js +20 -0
- package/dist/adapter/claude-code/probe/collectors/denied-call-collector.js +11 -0
- package/dist/adapter/claude-code/probe/collectors/identifier-collector.js +19 -0
- package/dist/adapter/claude-code/probe/collectors/line-collector.js +1 -0
- package/dist/adapter/claude-code/probe/collectors/line-type-collector.js +29 -0
- package/dist/adapter/claude-code/probe/collectors/sidechain-collector.js +20 -0
- package/dist/adapter/claude-code/probe/collectors/task-notification-collector.js +51 -0
- package/dist/adapter/claude-code/probe/collectors/tool-result-reference-collector.js +31 -0
- package/dist/adapter/claude-code/probe/collectors/tool-use-collector.js +24 -0
- package/dist/adapter/claude-code/probe/collectors/tool-version-collector.js +14 -0
- package/dist/adapter/claude-code/probe/collectors/top-level-key-collector.js +14 -0
- package/dist/adapter/claude-code/probe/collectors/unknown-line-type-key-collector.js +24 -0
- package/dist/adapter/claude-code/probe/collectors/working-directory-collector.js +28 -0
- package/dist/adapter/claude-code/probe/doctor-report.js +1 -0
- package/dist/adapter/claude-code/probe/meta-tally.js +42 -0
- package/dist/adapter/claude-code/probe/session-probe.js +1 -0
- package/dist/adapter/claude-code/probe/session-tally.js +41 -0
- package/dist/adapter/claude-code/probe/transcript-line.js +30 -0
- package/dist/adapter/claude-code/probe/transcript-tally.js +74 -0
- package/dist/adapter/claude-code/settings/deny-entries.js +65 -0
- package/dist/adapter/claude-code/settings/hook-entries.js +303 -0
- package/dist/adapter/codex/contract/actions.js +69 -0
- package/dist/adapter/codex/contract/assumptions.js +55 -0
- package/dist/adapter/codex/contract/capabilities.js +24 -0
- package/dist/adapter/codex/contract/delegations.js +30 -0
- package/dist/adapter/codex/contract/deliveries.js +25 -0
- package/dist/adapter/codex/contract/envelope.js +33 -0
- package/dist/adapter/codex/contract/hook-refusals.js +14 -0
- package/dist/adapter/codex/contract/hooks.js +46 -0
- package/dist/adapter/codex/contract/messages.js +47 -0
- package/dist/adapter/codex/contract/permissions.js +27 -0
- package/dist/adapter/codex/contract/reviews.js +13 -0
- package/dist/adapter/codex/contract/session.js +31 -0
- package/dist/adapter/codex/contract/turns.js +23 -0
- package/dist/adapter/codex/contract/version.js +15 -0
- package/dist/adapter/codex/discovery/codex-conversations.js +44 -0
- package/dist/adapter/codex/discovery/codex-project-catalogue.js +49 -0
- package/dist/adapter/codex/discovery/codex-recognition.js +20 -0
- package/dist/adapter/codex/discovery/codex-session-catalogue.js +28 -0
- package/dist/adapter/codex/discovery/codex-session-discovery.js +115 -0
- package/dist/adapter/codex/discovery/codex-session-index.js +21 -0
- package/dist/adapter/codex/discovery/codex-session-titles.js +135 -0
- package/dist/adapter/codex/discovery/session-header.js +86 -0
- package/dist/adapter/codex/discovery/session-owners.js +11 -0
- package/dist/adapter/codex/discovery/session-roots.js +49 -0
- package/dist/adapter/codex/events/action-items.js +138 -0
- package/dist/adapter/codex/events/capability-records.js +26 -0
- package/dist/adapter/codex/events/codex-session-source.js +121 -0
- package/dist/adapter/codex/events/hook-refusals.js +27 -0
- package/dist/adapter/codex/events/rollout-scan.js +614 -0
- package/dist/adapter/codex/events/turn-permissions.js +60 -0
- package/dist/adapter/codex/hooks/pre-tool-use-input.js +24 -0
- package/dist/adapter/codex/hooks/stop-refusals.js +57 -0
- package/dist/adapter/codex/probe/codex-doctor-report.js +1 -0
- package/dist/adapter/codex/probe/codex-probe.js +268 -0
- package/dist/adapter/codex/settings/codex-hooks.js +83 -0
- package/dist/cli/cli-command.js +1 -0
- package/dist/cli/command-router.js +42 -0
- package/dist/cli/commands/check-cli-command.js +128 -0
- package/dist/cli/commands/codex-stop-cli-command.js +27 -0
- package/dist/cli/commands/doctor-arguments.js +32 -0
- package/dist/cli/commands/doctor-cli-command.js +31 -0
- package/dist/cli/commands/doctor-usage.js +14 -0
- package/dist/cli/commands/init-cli-command.js +123 -0
- package/dist/cli/commands/menu-cli-command.js +58 -0
- package/dist/cli/commands/notify-cli-command.js +158 -0
- package/dist/cli/commands/refuse-cli-command.js +79 -0
- package/dist/cli/commands/report-arguments.js +62 -0
- package/dist/cli/commands/report-cli-command.js +36 -0
- package/dist/cli/commands/report-usage.js +41 -0
- package/dist/cli/commands/sessions-cli-command.js +184 -0
- package/dist/cli/commands/start-cli-command.js +83 -0
- package/dist/cli/commands/watch-cli-command.js +142 -0
- package/dist/cli/exit-codes.js +13 -0
- package/dist/cli/project-switches.js +46 -0
- package/dist/cli.js +80 -0
- package/dist/composition-root.js +411 -0
- package/dist/core/access/command-line.js +454 -0
- package/dist/core/access/listing.js +58 -0
- package/dist/core/access/path-shape.js +59 -0
- package/dist/core/access/path-tokens.js +37 -0
- package/dist/core/access/protected-access.js +310 -0
- package/dist/core/access/protected-values.js +102 -0
- package/dist/core/access/recorded-effect.js +67 -0
- package/dist/core/access/returns.js +173 -0
- package/dist/core/access/search-output.js +34 -0
- package/dist/core/access/search-reach.js +268 -0
- package/dist/core/access/uses.js +143 -0
- package/dist/core/access/words-before.js +52 -0
- package/dist/core/agent.js +1 -0
- package/dist/core/capability.js +11 -0
- package/dist/core/combined-project-catalogue.js +36 -0
- package/dist/core/combined-session-catalogue.js +25 -0
- package/dist/core/completeness.js +10 -0
- package/dist/core/context.js +1 -0
- package/dist/core/correlation/correlate.js +329 -0
- package/dist/core/delegation.js +1 -0
- package/dist/core/detector/prompt-signals.js +78 -0
- package/dist/core/entry-point.js +1 -0
- package/dist/core/event.js +1 -0
- package/dist/core/evidence.js +9 -0
- package/dist/core/late-message.js +32 -0
- package/dist/core/message.js +1 -0
- package/dist/core/nearest-project.js +28 -0
- package/dist/core/policy/default-policy.js +32 -0
- package/dist/core/policy/glob.js +56 -0
- package/dist/core/policy/parse-policy.js +70 -0
- package/dist/core/policy/policy.js +20 -0
- package/dist/core/policy/resolve-policy.js +16 -0
- package/dist/core/project-catalogue.js +1 -0
- package/dist/core/project-root.js +133 -0
- package/dist/core/provider-titles.js +10 -0
- package/dist/core/redaction/entropy.js +46 -0
- package/dist/core/redaction/redacted.js +4 -0
- package/dist/core/redaction/redactor.js +339 -0
- package/dist/core/redaction/secret-patterns.js +22 -0
- package/dist/core/redaction/value-shapes.js +81 -0
- package/dist/core/redaction/value-trace.js +110 -0
- package/dist/core/review.js +1 -0
- package/dist/core/session-catalogue.js +19 -0
- package/dist/core/session-filter.js +42 -0
- package/dist/core/session-format.js +27 -0
- package/dist/core/session-model.js +1 -0
- package/dist/core/session-reader.js +22 -0
- package/dist/core/session-records.js +1 -0
- package/dist/core/session-source.js +1 -0
- package/dist/core/session-titles.js +21 -0
- package/dist/core/turn.js +1 -0
- package/dist/doctor/codex-doctor.js +14 -0
- package/dist/doctor/doctor-use-case.js +1 -0
- package/dist/doctor/format-selecting-doctor.js +28 -0
- package/dist/doctor/render/attention/attention-rule.js +1 -0
- package/dist/doctor/render/attention/doctor-attention-rules.js +28 -0
- package/dist/doctor/render/attention/rules/damaged-meta-files-rule.js +8 -0
- package/dist/doctor/render/attention/rules/damaged-transcripts-rule.js +9 -0
- package/dist/doctor/render/attention/rules/incomplete-subagent-pairs-rule.js +6 -0
- package/dist/doctor/render/attention/rules/missing-main-transcript-rule.js +5 -0
- package/dist/doctor/render/attention/rules/missing-spilled-results-rule.js +6 -0
- package/dist/doctor/render/attention/rules/multiple-working-directories-rule.js +15 -0
- package/dist/doctor/render/attention/rules/unknown-denial-kinds-rule.js +5 -0
- package/dist/doctor/render/attention/rules/unknown-line-types-rule.js +6 -0
- package/dist/doctor/render/attention/rules/unrecognised-entries-rule.js +6 -0
- package/dist/doctor/render/attention/rules/unusable-directories-rule.js +12 -0
- package/dist/doctor/render/attention/transcript-scopes.js +6 -0
- package/dist/doctor/render/codex-text-doctor-renderer.js +97 -0
- package/dist/doctor/render/doctor-renderers.js +1 -0
- package/dist/doctor/render/json-doctor-renderer.js +7 -0
- package/dist/doctor/render/output-format.js +1 -0
- package/dist/doctor/render/text-doctor-renderer.js +124 -0
- package/dist/doctor/session-doctor.js +16 -0
- package/dist/infrastructure/clack-asker.js +24 -0
- package/dist/infrastructure/clack-chooser.js +40 -0
- package/dist/infrastructure/clack-multi-chooser.js +31 -0
- package/dist/infrastructure/file-alert-store.js +120 -0
- package/dist/infrastructure/file-checked-store.js +55 -0
- package/dist/infrastructure/file-mark-store.js +67 -0
- package/dist/infrastructure/file-onboarding-store.js +93 -0
- package/dist/infrastructure/folder-window.js +26 -0
- package/dist/infrastructure/node-agentwhy-invocation.js +99 -0
- package/dist/infrastructure/node-browser.js +40 -0
- package/dist/infrastructure/node-file-system.js +111 -0
- package/dist/infrastructure/node-local-server.js +115 -0
- package/dist/infrastructure/node-text-input.js +26 -0
- package/dist/infrastructure/os-notifier.js +21 -0
- package/dist/infrastructure/osascript-folder-chooser.js +53 -0
- package/dist/infrastructure/powershell-folder-chooser.js +78 -0
- package/dist/infrastructure/real-directory.js +18 -0
- package/dist/infrastructure/stream-printer.js +11 -0
- package/dist/infrastructure/terminal-banner.js +19 -0
- package/dist/ports/agentwhy-invocation.js +1 -0
- package/dist/ports/alert-store.js +1 -0
- package/dist/ports/asker.js +1 -0
- package/dist/ports/browser.js +1 -0
- package/dist/ports/checked-store.js +1 -0
- package/dist/ports/chooser.js +1 -0
- package/dist/ports/directory-reader.js +1 -0
- package/dist/ports/file-access-error.js +11 -0
- package/dist/ports/file-reader.js +1 -0
- package/dist/ports/file-tail-reader.js +1 -0
- package/dist/ports/file-writer.js +1 -0
- package/dist/ports/folder-chooser.js +1 -0
- package/dist/ports/local-server.js +1 -0
- package/dist/ports/mark-store.js +10 -0
- package/dist/ports/multi-chooser.js +1 -0
- package/dist/ports/notifier.js +1 -0
- package/dist/ports/onboarding-store.js +1 -0
- package/dist/ports/printer.js +1 -0
- package/dist/ports/text-input.js +1 -0
- package/dist/refuse/command-reach.js +135 -0
- package/dist/refuse/command-refusal.js +88 -0
- package/dist/refuse/render/codex-stop-words.js +21 -0
- package/dist/refuse/render/refusal-words.js +34 -0
- package/dist/report/build-report.js +1037 -0
- package/dist/report/check/actions-digest.js +73 -0
- package/dist/report/check/check-lines.js +83 -0
- package/dist/report/check/mark-request.js +90 -0
- package/dist/report/check/marks.js +84 -0
- package/dist/report/check/render/text-digest-renderer.js +332 -0
- package/dist/report/check/session-actions.js +90 -0
- package/dist/report/check/session-check.js +91 -0
- package/dist/report/choose-policy.js +61 -0
- package/dist/report/flow-reads.js +18 -0
- package/dist/report/private-files/tell-lists.js +84 -0
- package/dist/report/project-rules.js +33 -0
- package/dist/report/render/home-relative.js +18 -0
- package/dist/report/render/html-head.js +26 -0
- package/dist/report/render/html-report-components.js +48 -0
- package/dist/report/render/html-report-styles.js +500 -0
- package/dist/report/render/html-sidebar.js +42 -0
- package/dist/report/render/path-tail.js +14 -0
- package/dist/report/render/report-copy.js +1177 -0
- package/dist/report/render/report-page/advanced-view.js +167 -0
- package/dist/report/render/report-page/file-story.js +114 -0
- package/dist/report/render/report-page/files-view.js +381 -0
- package/dist/report/render/report-page/files.js +77 -0
- package/dist/report/render/report-page/fix-wizard-script.js +269 -0
- package/dist/report/render/report-page/fix-wizard.js +310 -0
- package/dist/report/render/report-page/helpers-view.js +383 -0
- package/dist/report/render/report-page/helpers.js +51 -0
- package/dist/report/render/report-page/item-names.js +63 -0
- package/dist/report/render/report-page/protect-patterns.js +13 -0
- package/dist/report/render/report-page/providers.js +208 -0
- package/dist/report/render/report-page/record-view.js +367 -0
- package/dist/report/render/report-page/report-page-renderer.js +129 -0
- package/dist/report/render/report-page/report-views.js +31 -0
- package/dist/report/render/report-page/story-window.js +356 -0
- package/dist/report/render/report-page/times.js +25 -0
- package/dist/report/render/report-page/to-do-view.js +299 -0
- package/dist/report/render/report-page/to-do.js +152 -0
- package/dist/report/render/report-page.js +1 -0
- package/dist/report/render/session-view.js +250 -0
- package/dist/report/render/text-report-renderer.js +981 -0
- package/dist/report/render/ui/add-file-popup.js +122 -0
- package/dist/report/render/ui/app-sidebar.js +78 -0
- package/dist/report/render/ui/ask-panel.js +80 -0
- package/dist/report/render/ui/avatar.js +19 -0
- package/dist/report/render/ui/backdrop.js +29 -0
- package/dist/report/render/ui/brand-mark.js +4 -0
- package/dist/report/render/ui/button.js +67 -0
- package/dist/report/render/ui/callout.js +20 -0
- package/dist/report/render/ui/chat-example.js +17 -0
- package/dist/report/render/ui/checklist.js +50 -0
- package/dist/report/render/ui/confirm-dialog.js +34 -0
- package/dist/report/render/ui/data-table.js +49 -0
- package/dist/report/render/ui/drawer.js +25 -0
- package/dist/report/render/ui/file-chip.js +37 -0
- package/dist/report/render/ui/fold-line.js +22 -0
- package/dist/report/render/ui/guide-card.js +25 -0
- package/dist/report/render/ui/hero.js +37 -0
- package/dist/report/render/ui/labelled-select.js +10 -0
- package/dist/report/render/ui/live-script.js +222 -0
- package/dist/report/render/ui/local-date.js +58 -0
- package/dist/report/render/ui/mode-icon.js +6 -0
- package/dist/report/render/ui/page-shell.js +101 -0
- package/dist/report/render/ui/pill-tabs.js +47 -0
- package/dist/report/render/ui/popup.js +77 -0
- package/dist/report/render/ui/progress.js +35 -0
- package/dist/report/render/ui/project-list.js +284 -0
- package/dist/report/render/ui/scope-choice.js +19 -0
- package/dist/report/render/ui/stats.js +21 -0
- package/dist/report/render/ui/status-icon.js +30 -0
- package/dist/report/render/ui/status-look.js +21 -0
- package/dist/report/render/ui/switch.js +11 -0
- package/dist/report/render/ui/tag.js +19 -0
- package/dist/report/render/ui/task-list.js +56 -0
- package/dist/report/render/ui/tokens.js +46 -0
- package/dist/report/render/ui/update-notice.js +146 -0
- package/dist/report/render/ui/words/app-words.js +163 -0
- package/dist/report/render/ui/words/conversations-words.js +457 -0
- package/dist/report/render/ui/words/month-words.js +59 -0
- package/dist/report/render/ui/words/onboarding-words.js +446 -0
- package/dist/report/render/ui/words/projects-words.js +217 -0
- package/dist/report/render/ui/words/report-words.js +2099 -0
- package/dist/report/render/ui/words/settings-words.js +611 -0
- package/dist/report/render/ui/words/to-fix-words.js +287 -0
- package/dist/report/report-model.js +2 -0
- package/dist/report/report-use-case.js +1 -0
- package/dist/report/rule-names.js +20 -0
- package/dist/report/session-report.js +163 -0
- package/dist/report/start/app-nav.js +37 -0
- package/dist/report/start/conversations/calendar-view.js +104 -0
- package/dist/report/start/conversations/conversation-columns.js +187 -0
- package/dist/report/start/conversations/conversations-renderer.js +54 -0
- package/dist/report/start/conversations/empty-week.js +120 -0
- package/dist/report/start/conversations/files-window.js +166 -0
- package/dist/report/start/conversations/period-section.js +280 -0
- package/dist/report/start/conversations/periods-script.js +440 -0
- package/dist/report/start/conversations/periods.js +110 -0
- package/dist/report/start/conversations/week-view.js +30 -0
- package/dist/report/start/conversations/weeks.js +17 -0
- package/dist/report/start/month/month-renderer.js +50 -0
- package/dist/report/start/month/month-view.js +135 -0
- package/dist/report/start/month/months.js +17 -0
- package/dist/report/start/onboarding/done.js +171 -0
- package/dist/report/start/onboarding/finish-onboarding.js +93 -0
- package/dist/report/start/onboarding/intro.js +100 -0
- package/dist/report/start/onboarding/onboarding-changes.js +40 -0
- package/dist/report/start/onboarding/onboarding-renderer.js +195 -0
- package/dist/report/start/onboarding/onboarding-script.js +400 -0
- package/dist/report/start/onboarding/onboarding-view.js +98 -0
- package/dist/report/start/onboarding/project-step.js +210 -0
- package/dist/report/start/onboarding/steps.js +239 -0
- package/dist/report/start/onboarding/welcome.js +66 -0
- package/dist/report/start/page-notice.js +10 -0
- package/dist/report/start/projects/index-projects.js +43 -0
- package/dist/report/start/projects/moved-page.js +82 -0
- package/dist/report/start/projects/project-switch.js +138 -0
- package/dist/report/start/projects/projects-window.js +67 -0
- package/dist/report/start/projects/temporary-space.js +18 -0
- package/dist/report/start/render/air-datepicker-vendor.js +27 -0
- package/dist/report/start/render/session-status.js +41 -0
- package/dist/report/start/render/start-words.js +84 -0
- package/dist/report/start/repository.js +28 -0
- package/dist/report/start/serve/index-handler.js +372 -0
- package/dist/report/start/serve/onboarding-request.js +50 -0
- package/dist/report/start/serve/settings-request.js +1 -0
- package/dist/report/start/serve/settings-setup.js +193 -0
- package/dist/report/start/session-index.js +1 -0
- package/dist/report/start/session-start.js +974 -0
- package/dist/report/start/settings/alerts-tab.js +104 -0
- package/dist/report/start/settings/files-tab.js +169 -0
- package/dist/report/start/settings/general-tab.js +71 -0
- package/dist/report/start/settings/settings-renderer.js +254 -0
- package/dist/report/start/settings/settings-script.js +161 -0
- package/dist/report/start/settings/settings-view.js +240 -0
- package/dist/report/start/settings/settings-windows.js +334 -0
- package/dist/report/start/settings-files.js +43 -0
- package/dist/report/start/to-fix/done-list.js +45 -0
- package/dist/report/start/to-fix/file-window.js +110 -0
- package/dist/report/start/to-fix/to-fix-list.js +70 -0
- package/dist/report/start/to-fix/to-fix-renderer.js +237 -0
- package/dist/report/start/to-fix/to-fix-script.js +94 -0
- package/dist/report/start/to-fix/to-fix-view.js +124 -0
- package/dist/report/watch/agent-alert.js +72 -0
- package/dist/report/watch/notice-choices.js +35 -0
- package/dist/report/watch/notice-settings.js +65 -0
- package/dist/report/watch/preferences.js +100 -0
- package/dist/report/watch/render/instruction-words.js +54 -0
- package/dist/report/watch/render/notice-words.js +182 -0
- package/dist/report/watch/subagent-watch.js +345 -0
- package/dist/report/watch/watch-notice.js +1 -0
- package/dist/setup/behind.js +18 -0
- package/dist/setup/codex-mirror.js +171 -0
- package/dist/setup/not-a-project.js +19 -0
- package/dist/setup/project-setup.js +644 -0
- package/dist/setup/protected-patterns.js +30 -0
- package/dist/shared/colour.js +23 -0
- package/dist/shared/compare.js +4 -0
- package/dist/shared/content-version.js +13 -0
- package/dist/shared/counter.js +11 -0
- package/dist/shared/file-stamp.js +4 -0
- package/dist/shared/json.js +13 -0
- package/dist/shared/label.js +13 -0
- package/dist/shared/package-name.js +6 -0
- package/dist/shared/plain-invocation.js +44 -0
- package/dist/shared/plain-version.js +21 -0
- package/dist/shared/printable.js +25 -0
- package/dist/shared/renderer.js +1 -0
- package/dist/shared/sentence.js +20 -0
- package/dist/shared/terminal-logo.js +41 -0
- package/dist/shared/text-table.js +15 -0
- package/dist/shared/wrap.js +29 -0
- package/package.json +70 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { escapeHtml as e } from '../../render/html-report-components.js';
|
|
2
|
+
import { pill } from '../../render/ui/button.js';
|
|
3
|
+
import { dayName } from '../../render/ui/local-date.js';
|
|
4
|
+
import { LOOKS } from '../../render/ui/status-look.js';
|
|
5
|
+
import { MODE_SVG } from '../../render/ui/mode-icon.js';
|
|
6
|
+
import { glyphIcon, statusIcon } from '../../render/ui/status-icon.js';
|
|
7
|
+
import { inLanguages, LANGS, translator } from '../../render/report-copy.js';
|
|
8
|
+
import { tag } from '../../render/ui/tag.js';
|
|
9
|
+
import { idInKey } from '../../../core/session-catalogue.js';
|
|
10
|
+
import { PROVIDER_NAMES } from '../../../core/session-format.js';
|
|
11
|
+
/**
|
|
12
|
+
* `When · What you asked · What happened · Your setting · Action` (`for-people-who-build-with-ai.md` F14; the
|
|
13
|
+
* maintainer's design of 2026-09-25, the fourth column named Your setting the same day), wherever conversations are listed: Conversations, and a day's window on This month. What the
|
|
14
|
+
* AI did and how many files it reached are one column - the look, counted where it read something, and under it "See
|
|
15
|
+
* all {n} files →", which opens F58's window. Whether it was fixed is the next one, so a read stays a read.
|
|
16
|
+
*/
|
|
17
|
+
export const CONVERSATION_TABLE = {
|
|
18
|
+
head: ['conv.col.when', 'conv.col.ask', 'conv.col.happened', 'conv.col.setting', 'conv.col.action'].map((key) => inLanguages((t) => t(key))),
|
|
19
|
+
columns: '110px minmax(220px,1.5fr) minmax(240px,1fr) 140px 150px',
|
|
20
|
+
minWidth: 1000,
|
|
21
|
+
attributes: ' data-conversations',
|
|
22
|
+
};
|
|
23
|
+
/** The day a conversation happened on: Today, Yesterday, or its date. */
|
|
24
|
+
function whenName(item) {
|
|
25
|
+
return inLanguages((t, lang) => (item.relative === undefined ? dayName(item.day, lang) : t('conv.day.' + item.relative)));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* One conversation as a row. What it says it did is its look; its Action button leads to its report, and a
|
|
29
|
+
* conversation with no report leads nowhere and says so rather than drawing a link that fails (P2). The row itself is
|
|
30
|
+
* not a link (the maintainer, 2026-09-25): a click beside the button, or on "See all {n} files", goes nowhere else.
|
|
31
|
+
*/
|
|
32
|
+
export function conversationRow(item, widen, include = false) {
|
|
33
|
+
const { entry } = item;
|
|
34
|
+
const report = entry.report.kind === 'generated' ? entry.report.file : undefined;
|
|
35
|
+
const title = entry.title === undefined ? undefined : e(entry.title);
|
|
36
|
+
const ask = title ?? inLanguages((t) => t('conv.untitled'));
|
|
37
|
+
const look = LOOKS[item.look];
|
|
38
|
+
const utc = new Date(entry.modifiedAt).toISOString().slice(0, 16).replace('T', ' ') + ' UTC';
|
|
39
|
+
// Cut from the id, not the key: every Codex key starts `codex-`, which told no row from another.
|
|
40
|
+
const bare = idInKey(entry.name);
|
|
41
|
+
const id = bare.length > 8 ? bare.slice(0, 8) + '…' : bare;
|
|
42
|
+
const tech = '<span class="cw-tech"><span title="' + e(entry.name) + '">' + e(id) + '</span> · ' + utc + ' · ' +
|
|
43
|
+
inLanguages((t) => t('conv.tech.helpers', { n: entry.delegations })) +
|
|
44
|
+
(item.look === 'outside' ? ' · ' + inLanguages((t) => t('conv.tech.widen', { command: '<code>' + e(widen) + '</code>' })) : '') + '</span>';
|
|
45
|
+
const action = look.needsFix && report !== undefined
|
|
46
|
+
? pill({ label: inLanguages((t) => t('conv.act.fix')), tone: 'primary', size: 'task', href: e(report) })
|
|
47
|
+
: report !== undefined
|
|
48
|
+
? pill({ label: inLanguages((t) => t('conv.act.see')), tone: 'outline', size: 'task', href: e(report) })
|
|
49
|
+
// F55: a conversation older than the run is checked on request, where the page can ask (not a shared one).
|
|
50
|
+
: item.look === 'outside' && include
|
|
51
|
+
? '<span class="cw-include-cell">' + pill({
|
|
52
|
+
label: inLanguages((t) => t('conv.act.include')),
|
|
53
|
+
tone: 'outline',
|
|
54
|
+
size: 'task',
|
|
55
|
+
button: true,
|
|
56
|
+
attributes: ' data-include="' + e(entry.name) + '" data-command="' + e(widen) + '" data-include-words="' + e(JSON.stringify(includeWords())) + '"',
|
|
57
|
+
}) + '<span class="cw-include-say" data-include-say hidden></span></span>'
|
|
58
|
+
: pill({ label: inLanguages((t) => t('conv.act.none')), tone: 'quiet', size: 'task' });
|
|
59
|
+
return {
|
|
60
|
+
cells: [
|
|
61
|
+
'<span class="cw-when">' + whenName(item) + '</span><span class="cw-time">' + item.time + '</span>',
|
|
62
|
+
// X28: every row names the AI the conversation was with, in the badge that says where something came from (§9.2).
|
|
63
|
+
'<span class="cw-ask">' + ask + '</span><span class="cw-ai">' + tag(e(PROVIDER_NAMES[entry.provider]), 'grey', 'badge') + '</span>' + tech,
|
|
64
|
+
whatHappened(item, report),
|
|
65
|
+
fixedCell(item.look),
|
|
66
|
+
'<span class="cw-action">' + action + '</span>',
|
|
67
|
+
],
|
|
68
|
+
// A read of files the person let it read is put before them too, with its bar, and leads to its report (F57a).
|
|
69
|
+
bar: look.attention,
|
|
70
|
+
...(look.tone === 'sand' ? { barTone: 'sand' } : {}),
|
|
71
|
+
// live-pages L7: a conversation the page did not have before is lit when it arrives.
|
|
72
|
+
attributes: ' data-live-key="' + e(entry.name) + '" data-day="' + item.day.number + '" data-look="' + item.look + '" data-search="' + e((entry.title ?? '').toLowerCase() + ' ' + item.files.join(' ').toLowerCase()) + '"',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* What happened: the look, counted where the AI read something ("Read 5 private files" - a count, never the names,
|
|
77
|
+
* guidelines §9.1), and under it the way to every file the conversation reached. The way is a link to the report's
|
|
78
|
+
* Files tab, which the page's script turns into F58's window. A conversation with no report, or none counted, has only
|
|
79
|
+
* its look: the look says why. A read every file of which was marked done is still drawn as the read it was, in coral
|
|
80
|
+
* (the maintainer, 2026-09-25: "…, now fixed" in mint read as if nothing had happened); the next column says it is fixed.
|
|
81
|
+
* A read of only files the person let it read is its own look, in Track's sand: it read them, and nothing was left to fix (F57a).
|
|
82
|
+
*/
|
|
83
|
+
function whatHappened(item, report) {
|
|
84
|
+
const look = item.look === 'fixed' ? 'read' : item.look;
|
|
85
|
+
const label = look === 'read' && item.read > 0 ? inLanguages((t) => t('conv.did.read', { n: item.read })) : undefined;
|
|
86
|
+
// A gap does not erase what the record established. Keep the uncertain look, and name its positive observation
|
|
87
|
+
// separately; the title only says what the person asked, while this count comes from confirmed file evidence.
|
|
88
|
+
const knownNames = item.look === 'unchecked' && item.entry.report.kind === 'generated'
|
|
89
|
+
? (item.entry.report.files ?? []).filter((file) => file.kind === 'named' || file.kind === 'result').length : 0;
|
|
90
|
+
const known = knownNames === 0 ? '' : '<span class="cw-known">' + inLanguages((t) => t('conv.did.partial.name', { n: knownNames })) + '</span>';
|
|
91
|
+
const n = item.reached ?? 0;
|
|
92
|
+
const all = report === undefined || n === 0 ? '' :
|
|
93
|
+
'<a class="cw-see" href="' + e(report) + '#files" data-all-files="' + e(report) + '">' + inLanguages((t) => t('conv.seeAll', { n })) + '</a>';
|
|
94
|
+
return '<span class="cw-did">' + statusIcon(look, label) + known + all + '</span>';
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Your setting: ✓ in mint once every file the AI read was marked done, ✕ in coral while one is not, and grey words where there
|
|
98
|
+
* was nothing to fix or where the run cannot tell (F16, F17): never an empty cell (guidelines §8). A read of only files
|
|
99
|
+
* the person chose Track for was never something to fix, and is not "nothing" either (the maintainer, 2026-09-25): it
|
|
100
|
+
* says the mode, with Settings' eye and words, in the sand of its look (F57a).
|
|
101
|
+
*/
|
|
102
|
+
function fixedCell(look) {
|
|
103
|
+
const say = (key) => inLanguages((t) => t(key));
|
|
104
|
+
if (look === 'fixed')
|
|
105
|
+
return glyphIcon('✓', 'mint', say('conv.fixed.yes'));
|
|
106
|
+
if (look === 'read')
|
|
107
|
+
return glyphIcon('✕', 'coral', say('conv.fixed.no'));
|
|
108
|
+
if (look === 'allowed')
|
|
109
|
+
return glyphIcon(MODE_SVG.tell, 'sand', say('set.mode.tell'));
|
|
110
|
+
return '<span class="cw-fixed-plain">' + say(LOOKS[look].known ? 'conv.fixed.na' : 'conv.fixed.unknown') + '</span>';
|
|
111
|
+
}
|
|
112
|
+
/** What the Check it button says as it works, in every language: one attribute cannot hold three. */
|
|
113
|
+
function includeWords() {
|
|
114
|
+
return Object.fromEntries(LANGS.map((lang) => {
|
|
115
|
+
const t = translator(lang);
|
|
116
|
+
return [lang, { saving: t('conv.include.saving'), refused: t('conv.include.refused'), asFile: t('conv.include.asFile'), unreachable: t('conv.include.unreachable') }];
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
export const CONVERSATION_COLUMNS_STYLE = String.raw `
|
|
120
|
+
.cw-when{display:block;font-size:15.5px;font-weight:600;white-space:nowrap}
|
|
121
|
+
.cw-time{display:block;font-size:14px;color:var(--text-3);margin-top:4px}
|
|
122
|
+
.cw-ask{display:block;font-size:16px;font-weight:500;line-height:1.4;overflow-wrap:anywhere}
|
|
123
|
+
.cw-ai{display:block;margin-top:6px}
|
|
124
|
+
.cw-tech{display:none;font-family:var(--mono);font-size:12.5px;color:var(--text-3);margin-top:7px;overflow-wrap:anywhere}
|
|
125
|
+
.cw-tech code{font-family:inherit;color:var(--text-2)}
|
|
126
|
+
.shell-main:has(#conv-tech:checked) .cw-tech{display:block}
|
|
127
|
+
.dt[data-conversations]{border-radius:18px}
|
|
128
|
+
.dt[data-conversations] .dt-head{padding:16px 24px;font-size:13.5px;column-gap:22px}
|
|
129
|
+
.dt[data-conversations] .dt-row{padding:20px 24px;column-gap:22px}
|
|
130
|
+
/* A group's heading reads as one (the maintainer, 2026-09-25): at the size of a row's words, not a label's. */
|
|
131
|
+
.dt[data-conversations] .dt-group{padding:14px 24px;font-size:15.5px;font-weight:650;letter-spacing:0;color:var(--text)}
|
|
132
|
+
.dt[data-conversations] .dt-group-cell{gap:10px}
|
|
133
|
+
.dt[data-conversations] .dt-group-dot{width:9px;height:9px}
|
|
134
|
+
.dt[data-conversations] .dt-group-count{font-size:15px;font-weight:600;color:var(--text-3)}
|
|
135
|
+
.cw-did{display:flex;flex-direction:column;align-items:flex-start;gap:5px}
|
|
136
|
+
.cw-did .look{gap:12px}
|
|
137
|
+
.cw-did .look-glyph{width:30px;height:30px;font-size:14px}
|
|
138
|
+
.cw-did .look-label{font-size:15.5px}
|
|
139
|
+
.cw-known{margin-left:42px;font-size:14px;line-height:1.35;color:var(--text-2)}
|
|
140
|
+
.cw-see{margin-left:42px;font-size:14px;font-weight:500;color:var(--text-2);text-decoration:underline;text-decoration-color:var(--white-28);text-underline-offset:5px;white-space:nowrap}
|
|
141
|
+
.cw-see:hover{color:var(--text);text-decoration-color:var(--text-2)}
|
|
142
|
+
.cw-fixed-plain{font-size:14px;color:var(--text-3);white-space:nowrap}
|
|
143
|
+
.cw-action{display:flex}
|
|
144
|
+
.cw-include-cell{display:flex;flex-direction:column;align-items:flex-start;gap:6px}
|
|
145
|
+
.cw-include-say{font-size:12.5px;line-height:1.45;color:var(--coral-text);max-width:220px}
|
|
146
|
+
.cw-include-say[hidden]{display:none}
|
|
147
|
+
.cw-include-say code{display:block;margin-top:4px;font-family:var(--mono);font-size:12px;color:var(--text);word-break:break-all;user-select:all}
|
|
148
|
+
`;
|
|
149
|
+
/**
|
|
150
|
+
* F55: **Check it** asks the page's server to write the report of a conversation older than the run, and reads the page
|
|
151
|
+
* again once it has, so the row shows what the report found. Opened as a file, it shows the command that includes it.
|
|
152
|
+
* The server's refusal is said in its own words (R59).
|
|
153
|
+
*/
|
|
154
|
+
export const CONVERSATION_ROW_SCRIPT = String.raw `
|
|
155
|
+
document.addEventListener('click', (event) => {
|
|
156
|
+
const button = event.target.closest('[data-include]');
|
|
157
|
+
if (!button) return;
|
|
158
|
+
const cell = button.closest('.cw-include-cell');
|
|
159
|
+
const line = cell && cell.querySelector('[data-include-say]');
|
|
160
|
+
const words = JSON.parse(button.dataset.includeWords || '{}');
|
|
161
|
+
const word = (key) => (words[document.documentElement.dataset.lang] || words.en || {})[key] || '';
|
|
162
|
+
const say = (text, command) => {
|
|
163
|
+
if (!line) return;
|
|
164
|
+
line.textContent = text;
|
|
165
|
+
if (command) {
|
|
166
|
+
const code = document.createElement('code');
|
|
167
|
+
code.textContent = command;
|
|
168
|
+
line.append(code);
|
|
169
|
+
}
|
|
170
|
+
line.hidden = false;
|
|
171
|
+
};
|
|
172
|
+
if (location.protocol !== 'http:' && location.protocol !== 'https:') { say(word('asFile'), button.dataset.command); return; }
|
|
173
|
+
button.disabled = true;
|
|
174
|
+
say(word('saving'));
|
|
175
|
+
fetch('api/include', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: button.dataset.include }) })
|
|
176
|
+
.then((response) => response.text().then((text) => {
|
|
177
|
+
let answer = {};
|
|
178
|
+
try { answer = JSON.parse(text); } catch { answer = { message: text.trim() }; }
|
|
179
|
+
return { ok: response.ok && answer.ok === true, message: answer.message || String(response.status) };
|
|
180
|
+
}), () => ({ ok: false, message: word('unreachable') }))
|
|
181
|
+
.then((answer) => {
|
|
182
|
+
if (answer.ok) { location.replace(location.pathname + '?at=' + Date.now() + location.hash); return; }
|
|
183
|
+
button.disabled = false;
|
|
184
|
+
say(word('refused') + ' ' + answer.message);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
`;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { INDEX_CONTENT_SECURITY_POLICY_META } from '../../render/html-head.js';
|
|
2
|
+
import { inLanguages } from '../../render/report-copy.js';
|
|
3
|
+
import { appSidebar } from '../../render/ui/app-sidebar.js';
|
|
4
|
+
import { ASK_PANEL_SCRIPT, ASK_PANEL_STYLE } from '../../render/ui/ask-panel.js';
|
|
5
|
+
import { pageShell } from '../../render/ui/page-shell.js';
|
|
6
|
+
import { appNav, sidebarProject } from '../app-nav.js';
|
|
7
|
+
import { projectsWindows } from '../projects/projects-window.js';
|
|
8
|
+
import { periodSection, PERIOD_PAGE_LIBRARIES, PERIOD_PAGE_SCRIPTS, PERIOD_PAGE_STYLES, TECH_TOGGLE } from './period-section.js';
|
|
9
|
+
import { emptyWeek, EMPTY_WEEK_STYLE } from './empty-week.js';
|
|
10
|
+
import { filesWindow, FILES_WINDOW_SCRIPTS, FILES_WINDOW_STYLES } from './files-window.js';
|
|
11
|
+
import { weekTitle, weekView } from './week-view.js';
|
|
12
|
+
import { conversationWeeks } from './weeks.js';
|
|
13
|
+
import { pageNotice } from '../page-notice.js';
|
|
14
|
+
/**
|
|
15
|
+
* The Conversations page `start` writes as `index.html` (`for-people-who-build-with-ai.md` §3 A; design file
|
|
16
|
+
* *agentwhy Sessions v2*): one week at a time, the answer first, then where to start, then the days, then what needs
|
|
17
|
+
* attention and, folded, the rest. It is made of the UI kit's pieces and adds only what is its own - the week view,
|
|
18
|
+
* the table's columns and the script that switches weeks (`.ai/plans/2026-09-23-conversations-redesign.md`).
|
|
19
|
+
*/
|
|
20
|
+
export class ConversationsRenderer {
|
|
21
|
+
#links;
|
|
22
|
+
constructor(links) {
|
|
23
|
+
this.#links = links;
|
|
24
|
+
}
|
|
25
|
+
render(index) {
|
|
26
|
+
const { weeks } = conversationWeeks(index);
|
|
27
|
+
return pageShell({
|
|
28
|
+
// which-project V2, V11: the person's projects, opened from the sidebar's card.
|
|
29
|
+
windows: projectsWindows(index),
|
|
30
|
+
title: 'conv.title',
|
|
31
|
+
// nothing-updates-by-itself U4: the update notice, where the project's hooks run an older release.
|
|
32
|
+
...pageNotice(index),
|
|
33
|
+
policy: INDEX_CONTENT_SECURITY_POLICY_META,
|
|
34
|
+
styles: [...PERIOD_PAGE_STYLES, ...FILES_WINDOW_STYLES, EMPTY_WEEK_STYLE, ASK_PANEL_STYLE],
|
|
35
|
+
libraries: PERIOD_PAGE_LIBRARIES,
|
|
36
|
+
scripts: [...PERIOD_PAGE_SCRIPTS, ...FILES_WINDOW_SCRIPTS, ASK_PANEL_SCRIPT],
|
|
37
|
+
sidebar: appSidebar({
|
|
38
|
+
...sidebarProject(index),
|
|
39
|
+
home: this.#links.conversations,
|
|
40
|
+
items: appNav(index, 'conversations', this.#links),
|
|
41
|
+
}),
|
|
42
|
+
main: TECH_TOGGLE + weeks.map((week, at) => periodSection(weeks, at, index, {
|
|
43
|
+
kind: 'week',
|
|
44
|
+
eyebrow: weekTitle(week),
|
|
45
|
+
view: weekView(weeks, at),
|
|
46
|
+
zero: 'conv.hero.fact.zero',
|
|
47
|
+
clean: inLanguages((t) => t('conv.clean.title')),
|
|
48
|
+
whole: 'conv.day.clear',
|
|
49
|
+
lists: true,
|
|
50
|
+
...(week.conversations.length === 0 ? { empty: emptyWeek(weeks, at, index, this.#links) } : {}),
|
|
51
|
+
})).join('') + filesWindow(),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { inLanguages } from '../../render/report-copy.js';
|
|
2
|
+
import { askPanel, askTrigger } from '../../render/ui/ask-panel.js';
|
|
3
|
+
import { settingsView } from '../settings/settings-view.js';
|
|
4
|
+
/** The written answers "✦ Nothing showing up?" opens: one box on the page, since only this week can be empty. */
|
|
5
|
+
const ASK = 'conv-ask';
|
|
6
|
+
/**
|
|
7
|
+
* This week, with no conversation in it yet (the maintainer's design, 2026-09-29): that it is normal, since when, and
|
|
8
|
+
* what keeps the private files meanwhile; then, under the days, what happens next and where to look when nothing shows
|
|
9
|
+
* up. Only the current week can be empty - a week nothing happened in is not offered (`weeks.ts`) - so every line may
|
|
10
|
+
* say "yet". Nothing is said that the model does not hold: the protection card only where the rules and `refuse` could
|
|
11
|
+
* both be read, and "Connected" only while the server answers the page's asks (`live-script.ts`).
|
|
12
|
+
*/
|
|
13
|
+
export function emptyWeek(weeks, at, index, links) {
|
|
14
|
+
const week = weeks[at];
|
|
15
|
+
const older = weeks[at + 1];
|
|
16
|
+
const protection = protectionOf(index);
|
|
17
|
+
const safe = protection?.blocked === true && !protection.chosen;
|
|
18
|
+
// On a Monday, "since Monday" is today.
|
|
19
|
+
const since = week.days[0]?.today === true ? 'conv.empty.lead.today' : 'conv.empty.lead';
|
|
20
|
+
return {
|
|
21
|
+
lead: inLanguages((t) => t(since) + (safe ? ' ' + t('conv.empty.safe') : '')),
|
|
22
|
+
...(protection === undefined ? {} : { guide: guideOf(protection, older, at, links) }),
|
|
23
|
+
after: nextSteps() + foot(),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Where the files are blocked whole (`block-means-blocked` K1, K2 - the rules and `refuse`, for every row the person
|
|
28
|
+
* chose to block), the mint lock, with the one way on: the week before. Where Settings would say "{n} private files
|
|
29
|
+
* aren't fully blocked", the coral card that leads there. Anything between is not claimed either way.
|
|
30
|
+
*/
|
|
31
|
+
function guideOf(protection, older, at, links) {
|
|
32
|
+
if (!protection.blocked) {
|
|
33
|
+
return {
|
|
34
|
+
tone: 'coral',
|
|
35
|
+
title: inLanguages((t) => t('conv.empty.gap', { n: protection.gaps })),
|
|
36
|
+
body: inLanguages((t) => t('conv.empty.gap.body')),
|
|
37
|
+
action: { label: inLanguages((t) => t('conv.empty.settings')), href: links.settings },
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
tone: 'mint',
|
|
42
|
+
mark: 'lock',
|
|
43
|
+
title: inLanguages((t) => t('conv.empty.on')),
|
|
44
|
+
body: inLanguages((t) => t(protection.chosen ? 'conv.empty.on.chosen' : 'conv.empty.on.body') + (protection.alert ? ' ' + t('conv.empty.on.alert') : '')),
|
|
45
|
+
...(older === undefined ? {} : {
|
|
46
|
+
action: {
|
|
47
|
+
label: inLanguages((t) => t(older.ago === 1 ? 'conv.empty.last' : 'conv.empty.earlier')),
|
|
48
|
+
href: '#week-' + older.ago,
|
|
49
|
+
attributes: ' data-period-go="' + (at + 1) + '"',
|
|
50
|
+
light: true,
|
|
51
|
+
},
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The project's protection, from the facts Settings shows (`settings-view.ts`), or undefined where any of them cannot be
|
|
57
|
+
* read - a shared page, a folder that is no project, a hook that reads a policy the page cannot see into.
|
|
58
|
+
*/
|
|
59
|
+
function protectionOf(index) {
|
|
60
|
+
const settings = index.settings;
|
|
61
|
+
if (settings === undefined || index.shared || index.notAProject !== undefined || settings.hooks === undefined || settings.held === undefined)
|
|
62
|
+
return undefined;
|
|
63
|
+
const view = settingsView(settings);
|
|
64
|
+
if (!view.known || !seen(view.reads) || !seen(settings.hooks.reads.refuse))
|
|
65
|
+
return undefined;
|
|
66
|
+
if (view.unfinished.rows > 0)
|
|
67
|
+
return { blocked: false, gaps: view.unfinished.rows };
|
|
68
|
+
const block = view.rows.filter((row) => row.mode === 'block');
|
|
69
|
+
if (block.length === 0 || !view.stop.on || block.some((row) => !row.watched))
|
|
70
|
+
return undefined;
|
|
71
|
+
return {
|
|
72
|
+
blocked: true,
|
|
73
|
+
// Files the person chose Tell me for are read, and told: "your private files stay blocked" would not be true of them (F57).
|
|
74
|
+
chosen: block.length < view.rows.length,
|
|
75
|
+
// A try at a blocked file is told only where `watch` runs and tells about the tries it stopped (F29, F30).
|
|
76
|
+
alert: view.alerts.on && view.stopped.on,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** The rules a hook reads are ones this page can list: the built-in list, or one of the project's two files. */
|
|
80
|
+
function seen(reads) {
|
|
81
|
+
return reads === 'default' || reads === 'local' || reads === 'shared';
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* "What happens next": three numbered cards. agentwhy reads Claude Code's and Codex's conversations and no other AI's
|
|
85
|
+
* (`proj.which`, which the answers below repeat), so the first names those two.
|
|
86
|
+
*/
|
|
87
|
+
function nextSteps() {
|
|
88
|
+
return '<section class="cw-next"><h2 class="cw-h2">' + inLanguages((t) => t('conv.next')) + '</h2><ol class="cw-next-list">' +
|
|
89
|
+
[1, 2, 3].map((n) => '<li class="cw-next-item"><span class="cw-next-n" aria-hidden="true">' + n + '</span>' +
|
|
90
|
+
'<span class="cw-next-title">' + inLanguages((t) => t('conv.next.' + n + '.title')) + '</span>' +
|
|
91
|
+
'<span class="cw-next-body">' + inLanguages((t) => t('conv.next.' + n + '.body')) + '</span></li>').join('') +
|
|
92
|
+
'</ol></section>';
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* "● Connected", drawn only while the server answers (`:root[data-live="on"]`); and "✦ Nothing showing up?", which
|
|
96
|
+
* opens written answers (F43: no model until O1 is decided, so no "Ask AI"). With no script the answers stand open.
|
|
97
|
+
*/
|
|
98
|
+
function foot() {
|
|
99
|
+
return '<div class="cw-empty-foot"><span class="cw-live"><span class="cw-live-dot" aria-hidden="true"></span>' +
|
|
100
|
+
inLanguages((t) => t('conv.live')) + '</span>' +
|
|
101
|
+
askTrigger(inLanguages((t) => t('conv.ask')), ASK) + '</div>' +
|
|
102
|
+
askPanel([
|
|
103
|
+
{ question: inLanguages((t) => t('conv.ask.which')), answer: inLanguages((t) => t('proj.which')) },
|
|
104
|
+
{ question: inLanguages((t) => t('conv.ask.where')), answer: inLanguages((t) => t('conv.ask.where.a')) },
|
|
105
|
+
], ASK);
|
|
106
|
+
}
|
|
107
|
+
export const EMPTY_WEEK_STYLE = String.raw `
|
|
108
|
+
.cw-next{margin:4px 0 20px}
|
|
109
|
+
.cw-next .cw-h2{margin-bottom:14px}
|
|
110
|
+
.cw-next-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}
|
|
111
|
+
.cw-next-item{display:flex;flex-direction:column;align-items:flex-start;padding:22px 22px 24px;border-radius:14px;background:var(--card);border:1px solid var(--white-09)}
|
|
112
|
+
.cw-next-n{display:flex;align-items:center;justify-content:center;width:28px;height:28px;margin-bottom:16px;border-radius:50%;background:var(--coral-14);color:var(--coral-text);font-size:14px;font-weight:650}
|
|
113
|
+
.cw-next-title{font-size:17px;font-weight:600;margin-bottom:6px}
|
|
114
|
+
.cw-next-body{font-size:15px;line-height:1.5;color:var(--text-2)}
|
|
115
|
+
.cw-empty-foot{display:flex;align-items:center;gap:8px 24px;flex-wrap:wrap}
|
|
116
|
+
.cw-live{display:none;align-items:center;gap:8px;font-size:14px;color:var(--text-2)}
|
|
117
|
+
:root[data-live="on"] .cw-live{display:inline-flex}
|
|
118
|
+
.cw-live-dot{width:7px;height:7px;border-radius:50%;background:var(--mint)}
|
|
119
|
+
.cw-empty-foot .ak-trigger{font-weight:600}
|
|
120
|
+
`;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { FILES_SCRIPT, FILES_VIEW_STYLE } from '../../render/report-page/files-view.js';
|
|
2
|
+
import { HELPERS_SCRIPT, HELPERS_VIEW_STYLE } from '../../render/report-page/helpers-view.js';
|
|
3
|
+
import { STORY_WINDOW_STYLE } from '../../render/report-page/story-window.js';
|
|
4
|
+
import { AVATAR_STYLE } from '../../render/ui/avatar.js';
|
|
5
|
+
import { PILL_TABS_SCRIPT, PILL_TABS_STYLE } from '../../render/ui/pill-tabs.js';
|
|
6
|
+
import { STAT_STYLE } from '../../render/ui/stats.js';
|
|
7
|
+
import { inLanguages, labelAttributes } from '../../render/report-copy.js';
|
|
8
|
+
import { closeButton, pill } from '../../render/ui/button.js';
|
|
9
|
+
import { LABELLED_SELECT_STYLE } from '../../render/ui/labelled-select.js';
|
|
10
|
+
import { CLOSES, popup, popupFoot, POPUP_SCRIPT, POPUP_STYLE } from '../../render/ui/popup.js';
|
|
11
|
+
import { TAG_STYLE } from '../../render/ui/tag.js';
|
|
12
|
+
const ID = 'conv-files';
|
|
13
|
+
/**
|
|
14
|
+
* Every file of one conversation, in a window (`for-people-who-build-with-ai.md` F58; O15 decided (b)): one window on
|
|
15
|
+
* the page, empty until a row's "See all {n} files" opens it - on Conversations, or in a day's window on This month,
|
|
16
|
+
* over which it opens. What it shows is not written here - it is the Files section
|
|
17
|
+
* of that conversation's report, read from the server that serves both, so the window and the report's tab are one
|
|
18
|
+
* view and cannot drift apart. Above it, what the person asked and when; under it, the way to the whole report.
|
|
19
|
+
*/
|
|
20
|
+
export function filesWindow() {
|
|
21
|
+
return popup({
|
|
22
|
+
id: ID,
|
|
23
|
+
size: 'wide',
|
|
24
|
+
labelledBy: ID + '-title',
|
|
25
|
+
body: '<div class="cwf-head"><p class="cwf-ask" id="' + ID + '-title">' +
|
|
26
|
+
inLanguages((t) => t('conv.files.asked', { ask: '<span data-files-ask></span>', when: '<span data-files-when></span>' })) + '</p>' +
|
|
27
|
+
closeButton(labelAttributes((t) => t('app.close')) + CLOSES) + '</div>' +
|
|
28
|
+
'<p class="cwf-loading" data-files-loading>' + inLanguages((t) => t('conv.files.loading')) + '</p>' +
|
|
29
|
+
'<div class="cwf-body" data-files-body></div>' +
|
|
30
|
+
// The windows of the files above, brought from the report with them; each opens over this one.
|
|
31
|
+
'<div data-files-windows></div>' +
|
|
32
|
+
popupFoot(inLanguages((t) => t('conv.files.note')), pill({ label: inLanguages((t) => t('app.close')), tone: 'outline', size: 'md', button: true, attributes: CLOSES }) +
|
|
33
|
+
pill({ label: inLanguages((t) => t('conv.files.full')), tone: 'outline', size: 'md', href: '#', attributes: ' data-files-full' })),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The maintainer's 2026-09-25 look: a little wider and taller than the kit's wide window, so the Files tab it holds
|
|
38
|
+
* has the whole width to itself.
|
|
39
|
+
*/
|
|
40
|
+
const FILES_WINDOW_STYLE = String.raw `
|
|
41
|
+
dialog#${ID}{max-width:1320px;max-height:calc(100vh - 64px);margin-top:32px}
|
|
42
|
+
.cwf-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:28px 40px 0}
|
|
43
|
+
.cwf-ask{margin:8px 0 0;font-size:14.5px;line-height:1.5;color:var(--text-2)}
|
|
44
|
+
.cwf-ask [data-files-ask]{color:var(--text);font-weight:600}
|
|
45
|
+
.cwf-loading{margin:0;padding:64px 40px;text-align:center;font-size:14px;color:var(--text-3)}
|
|
46
|
+
.cwf-loading[hidden]{display:none}
|
|
47
|
+
.cwf-body{padding:12px 40px 36px}
|
|
48
|
+
.cwf-body:empty{display:none}
|
|
49
|
+
.cwf-body .fl{max-width:none}
|
|
50
|
+
.cwf-body .fl .hero{margin-bottom:26px}
|
|
51
|
+
.cwf-body .fl .hero-fact,.cwf-body .fl .hero-action{font-size:34px}
|
|
52
|
+
#${ID} .pp-foot{padding:18px 40px}
|
|
53
|
+
@media (max-width:640px){dialog#${ID}{margin-top:16px;max-height:calc(100vh - 32px)}.cwf-head{padding:18px 18px 0}.cwf-body{padding:4px 18px 20px}.cwf-body .fl .hero-fact,.cwf-body .fl .hero-action{font-size:24px}#${ID} .pp-foot{padding:14px 18px}}
|
|
54
|
+
`;
|
|
55
|
+
/**
|
|
56
|
+
* Opens the window from a row's "See all {n} files", on a served page only: opened as a file, the page can read nothing
|
|
57
|
+
* beside it, and the button is the link it is written as. The report's Files section is taken as it is, with four
|
|
58
|
+
* changes: a row opens the window it opens on the report - what happened to that file, its story, diagram and record -
|
|
59
|
+
* brought over with it and opened here, over this one (the maintainer, 2026-09-25: a row that opened the report took
|
|
60
|
+
* the person off this page and out of the list they were reading; then, that every file opens that window), and a row
|
|
61
|
+
* whose window is not there leads nowhere and does not light up as a link; a link inside it or its window
|
|
62
|
+
* that names a place on the report (`#file-3`, `#protect-2`) leads to that place on the report, which opens the window
|
|
63
|
+
* it names (`POPUP_SCRIPT`); nothing in it is marked for a live update of this page to keep or light (`LIVE_SCRIPT`
|
|
64
|
+
* counts what this page marks); and no id of it is carried over, so none can stand twice. A read that fails follows
|
|
65
|
+
* the link instead.
|
|
66
|
+
*/
|
|
67
|
+
const CONVERSATION_FILES_SCRIPT = String.raw `
|
|
68
|
+
(() => {
|
|
69
|
+
const dialog = document.getElementById('${ID}');
|
|
70
|
+
if (!dialog || typeof dialog.showModal !== 'function') return;
|
|
71
|
+
const body = dialog.querySelector('[data-files-body]');
|
|
72
|
+
const loading = dialog.querySelector('[data-files-loading]');
|
|
73
|
+
const full = dialog.querySelector('[data-files-full]');
|
|
74
|
+
const held = dialog.querySelector('[data-files-windows]');
|
|
75
|
+
let asked = 0;
|
|
76
|
+
// A file's window closing is not this one closing: only this one's own close clears what it holds.
|
|
77
|
+
dialog.addEventListener('close', (event) => {
|
|
78
|
+
if (event.target !== dialog) return;
|
|
79
|
+
asked += 1;
|
|
80
|
+
body.replaceChildren();
|
|
81
|
+
if (held) held.replaceChildren();
|
|
82
|
+
});
|
|
83
|
+
document.addEventListener('click', (event) => {
|
|
84
|
+
const button = event.target.closest('[data-all-files]');
|
|
85
|
+
if (!button || (location.protocol !== 'http:' && location.protocol !== 'https:')) return;
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
event.stopPropagation();
|
|
88
|
+
const report = button.dataset.allFiles;
|
|
89
|
+
const row = button.closest('.dt-row');
|
|
90
|
+
const part = (selector) => (row && row.querySelector(selector) ? row.querySelector(selector).innerHTML : '');
|
|
91
|
+
dialog.querySelectorAll('[data-files-ask]').forEach((element) => { element.innerHTML = part('.cw-ask'); });
|
|
92
|
+
dialog.querySelectorAll('[data-files-when]').forEach((element) => { element.innerHTML = part('.cw-when') + ', ' + part('.cw-time'); });
|
|
93
|
+
if (full) full.setAttribute('href', report + '#files');
|
|
94
|
+
body.replaceChildren();
|
|
95
|
+
loading.hidden = false;
|
|
96
|
+
dialog.opener = button;
|
|
97
|
+
dialog.showModal();
|
|
98
|
+
const mine = ++asked;
|
|
99
|
+
fetch(report, { cache: 'no-store' })
|
|
100
|
+
.then((response) => (response.ok ? response.text() : Promise.reject(new Error(String(response.status)))))
|
|
101
|
+
.then((html) => {
|
|
102
|
+
if (mine !== asked) return;
|
|
103
|
+
const page = new DOMParser().parseFromString(html, 'text/html');
|
|
104
|
+
const files = page.getElementById('files');
|
|
105
|
+
if (!files) throw new Error('no Files section');
|
|
106
|
+
// Each row's window, taken before any id is dropped, under an id of this page's own.
|
|
107
|
+
const windows = [];
|
|
108
|
+
files.querySelectorAll('.dt-link').forEach((link) => {
|
|
109
|
+
const target = link.getAttribute('data-popup-open') || (link.getAttribute('href') || '').replace(/^#/, '');
|
|
110
|
+
const found = target ? page.getElementById(target) : null;
|
|
111
|
+
if (!found || found.tagName !== 'DIALOG') {
|
|
112
|
+
const row = link.closest('.dt-linked');
|
|
113
|
+
if (row) row.classList.remove('dt-linked');
|
|
114
|
+
link.remove();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const id = 'cwf-window-' + windows.length;
|
|
118
|
+
link.setAttribute('href', '#' + id);
|
|
119
|
+
link.setAttribute('data-cwf-open', id);
|
|
120
|
+
const title = found.getAttribute('aria-labelledby');
|
|
121
|
+
const heading = title ? found.querySelector('[id="' + title + '"]') : null;
|
|
122
|
+
if (heading) heading.setAttribute('data-cwf-title', '');
|
|
123
|
+
windows.push({ found, id });
|
|
124
|
+
});
|
|
125
|
+
// What is left leads to the report: a link that names a place on it goes there, where that window opens.
|
|
126
|
+
const detach = (root) => {
|
|
127
|
+
root.querySelectorAll('a[href^="#"]:not([data-cwf-open])').forEach((link) => link.setAttribute('href', report + link.getAttribute('href')));
|
|
128
|
+
root.querySelectorAll('[data-popup-open]').forEach((element) => element.removeAttribute('data-popup-open'));
|
|
129
|
+
root.querySelectorAll('[data-live-keep],[data-live-key]').forEach((element) => {
|
|
130
|
+
element.removeAttribute('data-live-keep');
|
|
131
|
+
element.removeAttribute('data-live-key');
|
|
132
|
+
});
|
|
133
|
+
root.querySelectorAll('[id]').forEach((element) => element.removeAttribute('id'));
|
|
134
|
+
};
|
|
135
|
+
detach(files);
|
|
136
|
+
files.querySelectorAll('[data-cwf-open]').forEach((link) => link.setAttribute('data-popup-open', link.getAttribute('data-cwf-open')));
|
|
137
|
+
windows.forEach(({ found, id }) => {
|
|
138
|
+
detach(found);
|
|
139
|
+
found.id = id;
|
|
140
|
+
found.setAttribute('aria-labelledby', id + '-title');
|
|
141
|
+
const heading = found.querySelector('[data-cwf-title]');
|
|
142
|
+
if (heading) heading.id = id + '-title';
|
|
143
|
+
});
|
|
144
|
+
const lang = document.documentElement.dataset.lang || 'en';
|
|
145
|
+
files.querySelectorAll('[data-placeholder-' + lang + ']').forEach((field) => { field.placeholder = field.getAttribute('data-placeholder-' + lang); });
|
|
146
|
+
loading.hidden = true;
|
|
147
|
+
body.replaceChildren(...[...document.importNode(files, true).childNodes]);
|
|
148
|
+
if (held) held.replaceChildren(...windows.map(({ found }) => document.importNode(found, true)));
|
|
149
|
+
if (window.agentwhyFiles) window.agentwhyFiles(body);
|
|
150
|
+
if (held && window.agentwhyDiagrams) window.agentwhyDiagrams(held);
|
|
151
|
+
})
|
|
152
|
+
.catch(() => {
|
|
153
|
+
if (mine !== asked) return;
|
|
154
|
+
dialog.close();
|
|
155
|
+
location.href = button.getAttribute('href');
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
})();
|
|
159
|
+
`;
|
|
160
|
+
/**
|
|
161
|
+
* What the window needs beyond the period pages' own: the kit's window, the report's Files view it shows, and a file's
|
|
162
|
+
* "What happened" window - its tabs, avatars, numbers and diagram - which opens over it.
|
|
163
|
+
*/
|
|
164
|
+
export const FILES_WINDOW_STYLES = [POPUP_STYLE, TAG_STYLE, LABELLED_SELECT_STYLE, FILES_VIEW_STYLE, PILL_TABS_STYLE, AVATAR_STYLE,
|
|
165
|
+
STAT_STYLE, HELPERS_VIEW_STYLE, STORY_WINDOW_STYLE, FILES_WINDOW_STYLE];
|
|
166
|
+
export const FILES_WINDOW_SCRIPTS = [POPUP_SCRIPT, PILL_TABS_SCRIPT, HELPERS_SCRIPT, FILES_SCRIPT, CONVERSATION_FILES_SCRIPT];
|