@yadsh/dsh-qa-surface 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +206 -11
- package/compatibility.json +10 -1
- package/cordis.patch.yml +11 -1
- package/lib/account-remotes.js +10 -0
- package/lib/account-remotes.js.map +1 -1
- package/lib/accounts/errors.js.map +1 -1
- package/lib/accounts/file.js.map +1 -1
- package/lib/accounts/store.js +22 -0
- package/lib/accounts/store.js.map +1 -1
- package/lib/attestation.js +6 -0
- package/lib/attestation.js.map +1 -1
- package/lib/client/QaAccountsController.js +29 -0
- package/lib/client/QaAccountsController.js.map +1 -1
- package/lib/client/QaSessionController.js +205 -61
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +125 -56
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaSurfaceGuard.js +96 -0
- package/lib/client/QaSurfaceGuard.js.map +1 -0
- package/lib/client/QaTranscriptAdapter.js +11 -5
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/attestation.js +14 -2
- package/lib/client/attestation.js.map +1 -1
- package/lib/client/components/QaChangelog.js +44 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaComposer.js +1 -1
- package/lib/client/components/QaComposer.js.map +1 -1
- package/lib/client/components/QaHeader.js +2 -8
- package/lib/client/components/QaHeader.js.map +1 -1
- package/lib/client/components/QaMessage.js +20 -7
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaModal.js +24 -6
- package/lib/client/components/QaModal.js.map +1 -1
- package/lib/client/components/QaSidebar.js +2 -6
- package/lib/client/components/QaSidebar.js.map +1 -1
- package/lib/client/components/QaSourcesPanel.js +6 -5
- package/lib/client/components/QaSourcesPanel.js.map +1 -1
- package/lib/client/components/QaWidthHandle.js +21 -1
- package/lib/client/components/QaWidthHandle.js.map +1 -1
- package/lib/client/components/surface-utils.js +2 -0
- package/lib/client/components/surface-utils.js.map +1 -1
- package/lib/client/index.js +72 -24
- package/lib/client/index.js.map +1 -1
- package/lib/client/panels/PanelHost.js +209 -0
- package/lib/client/panels/PanelHost.js.map +1 -0
- package/lib/client/panels/PanelLauncher.js +39 -0
- package/lib/client/panels/PanelLauncher.js.map +1 -0
- package/lib/client/panels/contract.js +2 -0
- package/lib/client/panels/contract.js.map +1 -0
- package/lib/client/panels/index.js +2 -0
- package/lib/client/panels/index.js.map +1 -0
- package/lib/client/panels/registry.js +171 -0
- package/lib/client/panels/registry.js.map +1 -0
- package/lib/client/project-session-state.js +13 -5
- package/lib/client/project-session-state.js.map +1 -1
- package/lib/client/settings/card.js +2 -2
- package/lib/client/settings/card.js.map +1 -1
- package/lib/client/settings/sections/accounts.js +3 -1
- package/lib/client/settings/sections/accounts.js.map +1 -1
- package/lib/client/settings/sections/documents.js +88 -0
- package/lib/client/settings/sections/documents.js.map +1 -0
- package/lib/client/settings/sections/interface.js +2 -0
- package/lib/client/settings/sections/interface.js.map +1 -1
- package/lib/client/settings/sections.js +1 -0
- package/lib/client/settings/sections.js.map +1 -1
- package/lib/client/settings-extensions/contract.js +2 -0
- package/lib/client/settings-extensions/contract.js.map +1 -0
- package/lib/client/settings-extensions/index.js +2 -0
- package/lib/client/settings-extensions/index.js.map +1 -0
- package/lib/client/settings-extensions/registry.js +63 -0
- package/lib/client/settings-extensions/registry.js.map +1 -0
- package/lib/client/settlement.js +51 -5
- package/lib/client/settlement.js.map +1 -1
- package/lib/client/source-preview.js +24 -0
- package/lib/client/source-preview.js.map +1 -0
- package/lib/client/styles.js +158 -32
- package/lib/client/styles.js.map +1 -1
- package/lib/client/subagent-codenames.js +109 -0
- package/lib/client/subagent-codenames.js.map +1 -0
- package/lib/client/types.js +2 -0
- package/lib/client/types.js.map +1 -1
- package/lib/client/user-settings/GeneralSettingsPage.js +13 -0
- package/lib/client/user-settings/GeneralSettingsPage.js.map +1 -0
- package/lib/client/user-settings/ProfileSettingsPage.js +59 -0
- package/lib/client/user-settings/ProfileSettingsPage.js.map +1 -0
- package/lib/client/user-settings/SkillCatalog.js +23 -0
- package/lib/client/user-settings/SkillCatalog.js.map +1 -0
- package/lib/client/user-settings/SkillEditor.js +89 -0
- package/lib/client/user-settings/SkillEditor.js.map +1 -0
- package/lib/client/user-settings/SkillToolPicker.js +58 -0
- package/lib/client/user-settings/SkillToolPicker.js.map +1 -0
- package/lib/client/user-settings/SkillsSettingsPage.js +171 -0
- package/lib/client/user-settings/SkillsSettingsPage.js.map +1 -0
- package/lib/client/user-settings/StartersSettingsPage.js +78 -0
- package/lib/client/user-settings/StartersSettingsPage.js.map +1 -0
- package/lib/client/user-settings/UserSettingsDialog.js +50 -0
- package/lib/client/user-settings/UserSettingsDialog.js.map +1 -0
- package/lib/client/user-settings/copy.js +84 -0
- package/lib/client/user-settings/copy.js.map +1 -0
- package/lib/client/user-settings/draft.js +127 -0
- package/lib/client/user-settings/draft.js.map +1 -0
- package/lib/client/user-settings/fields.js +24 -0
- package/lib/client/user-settings/fields.js.map +1 -0
- package/lib/client.js +5554 -1415
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/accounts.js +30 -0
- package/lib/config-resolvers/accounts.js.map +1 -1
- package/lib/config-resolvers/defaults.js +23 -0
- package/lib/config-resolvers/defaults.js.map +1 -1
- package/lib/config-resolvers/tools.js +37 -0
- package/lib/config-resolvers/tools.js.map +1 -0
- package/lib/config-resolvers/ui.js +2 -0
- package/lib/config-resolvers/ui.js.map +1 -1
- package/lib/config.js +288 -0
- package/lib/config.js.map +1 -1
- package/lib/documents/artifacts/ids.js +43 -0
- package/lib/documents/artifacts/ids.js.map +1 -0
- package/lib/documents/artifacts/manifest.js +66 -0
- package/lib/documents/artifacts/manifest.js.map +1 -0
- package/lib/documents/artifacts/store.js +169 -0
- package/lib/documents/artifacts/store.js.map +1 -0
- package/lib/documents/capabilities.js +93 -0
- package/lib/documents/capabilities.js.map +1 -0
- package/lib/documents/config.js +302 -0
- package/lib/documents/config.js.map +1 -0
- package/lib/documents/defaults.js +78 -0
- package/lib/documents/defaults.js.map +1 -0
- package/lib/documents/errors.js +101 -0
- package/lib/documents/errors.js.map +1 -0
- package/lib/documents/index.js +80 -0
- package/lib/documents/index.js.map +1 -0
- package/lib/documents/inspect/facts.js +161 -0
- package/lib/documents/inspect/facts.js.map +1 -0
- package/lib/documents/inspect/zip.js +108 -0
- package/lib/documents/inspect/zip.js.map +1 -0
- package/lib/documents/markdown/directives.js +135 -0
- package/lib/documents/markdown/directives.js.map +1 -0
- package/lib/documents/markdown/frontmatter.js +35 -0
- package/lib/documents/markdown/frontmatter.js.map +1 -0
- package/lib/documents/markdown/normalize.js +113 -0
- package/lib/documents/markdown/normalize.js.map +1 -0
- package/lib/documents/orchestrator/assets.js +243 -0
- package/lib/documents/orchestrator/assets.js.map +1 -0
- package/lib/documents/orchestrator/convert-document.js +186 -0
- package/lib/documents/orchestrator/convert-document.js.map +1 -0
- package/lib/documents/orchestrator/create-document.js +292 -0
- package/lib/documents/orchestrator/create-document.js.map +1 -0
- package/lib/documents/orchestrator/extract-document.js +162 -0
- package/lib/documents/orchestrator/extract-document.js.map +1 -0
- package/lib/documents/orchestrator/inspect-document.js +89 -0
- package/lib/documents/orchestrator/inspect-document.js.map +1 -0
- package/lib/documents/orchestrator/runtime-deps.js +59 -0
- package/lib/documents/orchestrator/runtime-deps.js.map +1 -0
- package/lib/documents/orchestrator/scope.js +132 -0
- package/lib/documents/orchestrator/scope.js.map +1 -0
- package/lib/documents/providers/docling.js +247 -0
- package/lib/documents/providers/docling.js.map +1 -0
- package/lib/documents/providers/libreoffice.js +130 -0
- package/lib/documents/providers/libreoffice.js.map +1 -0
- package/lib/documents/providers/markitdown.js +89 -0
- package/lib/documents/providers/markitdown.js.map +1 -0
- package/lib/documents/providers/pandoc.js +161 -0
- package/lib/documents/providers/pandoc.js.map +1 -0
- package/lib/documents/providers/process.js +164 -0
- package/lib/documents/providers/process.js.map +1 -0
- package/lib/documents/providers/registry.js +152 -0
- package/lib/documents/providers/registry.js.map +1 -0
- package/lib/documents/providers/shared.js +75 -0
- package/lib/documents/providers/shared.js.map +1 -0
- package/lib/documents/runtime.js +114 -0
- package/lib/documents/runtime.js.map +1 -0
- package/lib/documents/security/file-types.js +188 -0
- package/lib/documents/security/file-types.js.map +1 -0
- package/lib/documents/security/limits.js +78 -0
- package/lib/documents/security/limits.js.map +1 -0
- package/lib/documents/security/mime.js +43 -0
- package/lib/documents/security/mime.js.map +1 -0
- package/lib/documents/security/paths.js +133 -0
- package/lib/documents/security/paths.js.map +1 -0
- package/lib/documents/templates/registry.js +147 -0
- package/lib/documents/templates/registry.js.map +1 -0
- package/lib/documents/templates/resolver.js +59 -0
- package/lib/documents/templates/resolver.js.map +1 -0
- package/lib/documents/tools/convert.js +125 -0
- package/lib/documents/tools/convert.js.map +1 -0
- package/lib/documents/tools/create.js +187 -0
- package/lib/documents/tools/create.js.map +1 -0
- package/lib/documents/tools/index.js +41 -0
- package/lib/documents/tools/index.js.map +1 -0
- package/lib/documents/tools/inspect.js +135 -0
- package/lib/documents/tools/inspect.js.map +1 -0
- package/lib/documents/tools/shared.js +88 -0
- package/lib/documents/tools/shared.js.map +1 -0
- package/lib/documents/tools/to-markdown.js +125 -0
- package/lib/documents/tools/to-markdown.js.map +1 -0
- package/lib/documents/types.js +12 -0
- package/lib/documents/types.js.map +1 -0
- package/lib/index.js +231 -22
- package/lib/index.js.map +1 -1
- package/lib/integration-principals.js +22 -0
- package/lib/integration-principals.js.map +1 -0
- package/lib/lockdown-policy.js +15 -3
- package/lib/lockdown-policy.js.map +1 -1
- package/lib/personal-skills/errors.js +9 -0
- package/lib/personal-skills/errors.js.map +1 -0
- package/lib/personal-skills/host.js +80 -0
- package/lib/personal-skills/host.js.map +1 -0
- package/lib/personal-skills/index.js +10 -0
- package/lib/personal-skills/index.js.map +1 -0
- package/lib/personal-skills/paths.js +127 -0
- package/lib/personal-skills/paths.js.map +1 -0
- package/lib/personal-skills/provider.js +109 -0
- package/lib/personal-skills/provider.js.map +1 -0
- package/lib/personal-skills/remotes.js +40 -0
- package/lib/personal-skills/remotes.js.map +1 -0
- package/lib/personal-skills/service.js +686 -0
- package/lib/personal-skills/service.js.map +1 -0
- package/lib/personal-skills/skill-file.js +278 -0
- package/lib/personal-skills/skill-file.js.map +1 -0
- package/lib/personal-skills/skill-format.js +202 -0
- package/lib/personal-skills/skill-format.js.map +1 -0
- package/lib/personal-skills/watcher.js +96 -0
- package/lib/personal-skills/watcher.js.map +1 -0
- package/lib/profile.js +6 -4
- package/lib/profile.js.map +1 -1
- package/lib/prompt-notes.js +19 -0
- package/lib/prompt-notes.js.map +1 -1
- package/lib/provenance/file-preview.js +68 -21
- package/lib/provenance/file-preview.js.map +1 -1
- package/lib/provenance/host-store.js +44 -11
- package/lib/provenance/host-store.js.map +1 -1
- package/lib/provenance/index.js +1 -0
- package/lib/provenance/index.js.map +1 -1
- package/lib/provenance/normalize.js +3 -1
- package/lib/provenance/normalize.js.map +1 -1
- package/lib/provenance/snapshot-store.js +154 -0
- package/lib/provenance/snapshot-store.js.map +1 -0
- package/lib/qa-tools/activation-detector.js +53 -0
- package/lib/qa-tools/activation-detector.js.map +1 -0
- package/lib/qa-tools/activation-manager.js +111 -0
- package/lib/qa-tools/activation-manager.js.map +1 -0
- package/lib/qa-tools/catalog.js +108 -0
- package/lib/qa-tools/catalog.js.map +1 -0
- package/lib/qa-tools/durable-marker.js +115 -0
- package/lib/qa-tools/durable-marker.js.map +1 -0
- package/lib/qa-tools/index.js +83 -0
- package/lib/qa-tools/index.js.map +1 -0
- package/lib/qa-tools/lifecycle.js +64 -0
- package/lib/qa-tools/lifecycle.js.map +1 -0
- package/lib/qa-tools/types.js +2 -0
- package/lib/qa-tools/types.js.map +1 -0
- package/lib/resolve-config.js +5 -0
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +75 -18
- package/lib/secure-session.js.map +1 -1
- package/lib/starters.js +117 -0
- package/lib/starters.js.map +1 -0
- package/lib/typert.host.js +767 -22
- package/lib/typert.remote-client.d.ts +17 -1
- package/lib/typert.remote-client.js +609 -17
- package/lib/types/account-remotes.d.ts +3 -1
- package/lib/types/accounts/errors.d.ts +1 -1
- package/lib/types/accounts/file.d.ts +10 -0
- package/lib/types/accounts/store.d.ts +7 -1
- package/lib/types/attestation.d.ts +2 -0
- package/lib/types/client/QaAccountsController.d.ts +7 -1
- package/lib/types/client/QaSessionController.d.ts +14 -0
- package/lib/types/client/QaSurface.d.ts +14 -4
- package/lib/types/client/QaSurfaceGuard.d.ts +27 -0
- package/lib/types/client/QaTranscriptAdapter.d.ts +7 -0
- package/lib/types/client/attestation.d.ts +8 -1
- package/lib/types/client/components/QaComposer.d.ts +3 -1
- package/lib/types/client/components/QaHeader.d.ts +3 -1
- package/lib/types/client/components/QaModal.d.ts +5 -4
- package/lib/types/client/components/QaSidebar.d.ts +8 -11
- package/lib/types/client/components/QaWidthHandle.d.ts +13 -0
- package/lib/types/client/index.d.ts +1 -0
- package/lib/types/client/panels/PanelHost.d.ts +18 -0
- package/lib/types/client/panels/PanelLauncher.d.ts +5 -0
- package/lib/types/client/panels/contract.d.ts +83 -0
- package/lib/types/client/panels/index.d.ts +3 -0
- package/lib/types/client/panels/registry.d.ts +40 -0
- package/lib/types/client/project-session-state.d.ts +7 -0
- package/lib/types/client/settings/sections/documents.d.ts +13 -0
- package/lib/types/client/settings/sections.d.ts +1 -0
- package/lib/types/client/settings-extensions/contract.d.ts +32 -0
- package/lib/types/client/settings-extensions/index.d.ts +3 -0
- package/lib/types/client/settings-extensions/registry.d.ts +15 -0
- package/lib/types/client/settlement.d.ts +41 -5
- package/lib/types/client/source-preview.d.ts +8 -0
- package/lib/types/client/styles.d.ts +2 -0
- package/lib/types/client/subagent-codenames.d.ts +18 -0
- package/lib/types/client/types.d.ts +35 -3
- package/lib/types/client/user-settings/GeneralSettingsPage.d.ts +14 -0
- package/lib/types/client/user-settings/ProfileSettingsPage.d.ts +18 -0
- package/lib/types/client/user-settings/SkillCatalog.d.ts +16 -0
- package/lib/types/client/user-settings/SkillEditor.d.ts +42 -0
- package/lib/types/client/user-settings/SkillToolPicker.d.ts +17 -0
- package/lib/types/client/user-settings/SkillsSettingsPage.d.ts +15 -0
- package/lib/types/client/user-settings/StartersSettingsPage.d.ts +14 -0
- package/lib/types/client/user-settings/UserSettingsDialog.d.ts +43 -0
- package/lib/types/client/user-settings/copy.d.ts +25 -0
- package/lib/types/client/user-settings/draft.d.ts +51 -0
- package/lib/types/client/user-settings/fields.d.ts +43 -0
- package/lib/types/config-resolvers/tools.d.ts +6 -0
- package/lib/types/documents/artifacts/ids.d.ts +14 -0
- package/lib/types/documents/artifacts/manifest.d.ts +32 -0
- package/lib/types/documents/artifacts/store.d.ts +67 -0
- package/lib/types/documents/capabilities.d.ts +32 -0
- package/lib/types/documents/config.d.ts +27 -0
- package/lib/types/documents/defaults.d.ts +161 -0
- package/lib/types/documents/errors.d.ts +42 -0
- package/lib/types/documents/index.d.ts +63 -0
- package/lib/types/documents/inspect/facts.d.ts +43 -0
- package/lib/types/documents/inspect/zip.d.ts +28 -0
- package/lib/types/documents/markdown/directives.d.ts +39 -0
- package/lib/types/documents/markdown/frontmatter.d.ts +15 -0
- package/lib/types/documents/markdown/normalize.d.ts +30 -0
- package/lib/types/documents/orchestrator/assets.d.ts +55 -0
- package/lib/types/documents/orchestrator/convert-document.d.ts +25 -0
- package/lib/types/documents/orchestrator/create-document.d.ts +18 -0
- package/lib/types/documents/orchestrator/extract-document.d.ts +24 -0
- package/lib/types/documents/orchestrator/inspect-document.d.ts +12 -0
- package/lib/types/documents/orchestrator/runtime-deps.d.ts +43 -0
- package/lib/types/documents/orchestrator/scope.d.ts +52 -0
- package/lib/types/documents/providers/docling.d.ts +54 -0
- package/lib/types/documents/providers/libreoffice.d.ts +40 -0
- package/lib/types/documents/providers/markitdown.d.ts +28 -0
- package/lib/types/documents/providers/pandoc.d.ts +42 -0
- package/lib/types/documents/providers/process.d.ts +54 -0
- package/lib/types/documents/providers/registry.d.ts +68 -0
- package/lib/types/documents/providers/shared.d.ts +27 -0
- package/lib/types/documents/runtime.d.ts +59 -0
- package/lib/types/documents/security/file-types.d.ts +39 -0
- package/lib/types/documents/security/limits.d.ts +24 -0
- package/lib/types/documents/security/mime.d.ts +13 -0
- package/lib/types/documents/security/paths.d.ts +38 -0
- package/lib/types/documents/templates/registry.d.ts +50 -0
- package/lib/types/documents/templates/resolver.d.ts +30 -0
- package/lib/types/documents/tools/convert.d.ts +9 -0
- package/lib/types/documents/tools/create.d.ts +14 -0
- package/lib/types/documents/tools/index.d.ts +33 -0
- package/lib/types/documents/tools/inspect.d.ts +9 -0
- package/lib/types/documents/tools/shared.d.ts +77 -0
- package/lib/types/documents/tools/to-markdown.d.ts +12 -0
- package/lib/types/documents/types.d.ts +294 -0
- package/lib/types/index.d.ts +75 -3
- package/lib/types/integration-principals.d.ts +9 -0
- package/lib/types/lockdown-policy.d.ts +12 -2
- package/lib/types/personal-skills/errors.d.ts +11 -0
- package/lib/types/personal-skills/host.d.ts +42 -0
- package/lib/types/personal-skills/index.d.ts +10 -0
- package/lib/types/personal-skills/paths.d.ts +39 -0
- package/lib/types/personal-skills/provider.d.ts +33 -0
- package/lib/types/personal-skills/remotes.d.ts +35 -0
- package/lib/types/personal-skills/service.d.ts +131 -0
- package/lib/types/personal-skills/skill-file.d.ts +64 -0
- package/lib/types/personal-skills/skill-format.d.ts +100 -0
- package/lib/types/personal-skills/watcher.d.ts +39 -0
- package/lib/types/profile.d.ts +13 -0
- package/lib/types/prompt-notes.d.ts +9 -0
- package/lib/types/provenance/file-preview.d.ts +47 -4
- package/lib/types/provenance/host-store.d.ts +7 -1
- package/lib/types/provenance/index.d.ts +1 -0
- package/lib/types/provenance/snapshot-store.d.ts +23 -0
- package/lib/types/qa-tools/activation-detector.d.ts +29 -0
- package/lib/types/qa-tools/activation-manager.d.ts +47 -0
- package/lib/types/qa-tools/catalog.d.ts +40 -0
- package/lib/types/qa-tools/durable-marker.d.ts +16 -0
- package/lib/types/qa-tools/index.d.ts +40 -0
- package/lib/types/qa-tools/lifecycle.d.ts +44 -0
- package/lib/types/qa-tools/types.d.ts +45 -0
- package/lib/types/secure-session.d.ts +33 -2
- package/lib/types/starters.d.ts +45 -0
- package/lib/types/types.d.ts +208 -3
- package/package.json +22 -9
- package/scripts/repair-session-events.mjs +260 -0
- package/lib/client/components/QaProfile.js +0 -64
- package/lib/client/components/QaProfile.js.map +0 -1
- package/lib/types/client/components/QaProfile.d.ts +0 -25
package/lib/types/types.d.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
import type { QaDocumentsConfig, ResolvedQaDocumentsConfig } from "./documents/config.js";
|
|
1
2
|
import type { QaTurnSources } from "./provenance/types.js";
|
|
2
3
|
export type QaSessionPolicy = "browser-persistent" | "new-on-load" | "fixed";
|
|
3
4
|
export type QaSandboxMode = "read-only" | "workspace-write";
|
|
4
5
|
export type QaApprovalPolicy = "never";
|
|
5
6
|
export type QaToolPolicyMode = "allow-list";
|
|
7
|
+
/**
|
|
8
|
+
* How the QA tool catalog is attached. `all` attaches the whole catalog once
|
|
9
|
+
* the activation skill loads; the field is reserved so a future grouped or
|
|
10
|
+
* searched mode needs no config redesign.
|
|
11
|
+
*/
|
|
12
|
+
export type QaToolActivationMode = "all";
|
|
6
13
|
/**
|
|
7
14
|
* How a tool policy `ask` resolves on an attested QA agent. `blocked` refuses
|
|
8
15
|
* the call with the surface's own reason; `interactive` parks it until the
|
|
@@ -34,6 +41,8 @@ export interface QaAccountUserPublic {
|
|
|
34
41
|
readonly disabled: boolean;
|
|
35
42
|
/** Self-declared identity the QA prompt renders; empty until edited. */
|
|
36
43
|
readonly profile: QaAccountProfile;
|
|
44
|
+
/** The account's own starter buttons; empty until customized. */
|
|
45
|
+
readonly starters: QaAccountStarters;
|
|
37
46
|
}
|
|
38
47
|
/** One external system the deployment collects a handle for. */
|
|
39
48
|
export interface QaAccountIdentityField {
|
|
@@ -63,6 +72,26 @@ export interface QaAccountProfileInput {
|
|
|
63
72
|
readonly identities: Readonly<Record<string, string>>;
|
|
64
73
|
readonly instructions: string;
|
|
65
74
|
}
|
|
75
|
+
/** One starter button: what it reads and what pressing it sends. */
|
|
76
|
+
export interface QaAccountStarter {
|
|
77
|
+
readonly label: string;
|
|
78
|
+
readonly prompt: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* An account's own starter buttons plus the choice about the deployment's
|
|
82
|
+
* built-in suggestions. Pure UI preferences: unlike the profile, none of this
|
|
83
|
+
* reaches the agent prompt.
|
|
84
|
+
*/
|
|
85
|
+
export interface QaAccountStarters {
|
|
86
|
+
readonly items: readonly QaAccountStarter[];
|
|
87
|
+
/** Hide the deployment's suggested questions in this account's composer. */
|
|
88
|
+
readonly hideDefaults: boolean;
|
|
89
|
+
}
|
|
90
|
+
/** Full-replace starters write: an absent value clears the stored one. */
|
|
91
|
+
export interface QaAccountStartersInput {
|
|
92
|
+
readonly items: readonly QaAccountStarter[];
|
|
93
|
+
readonly hideDefaults: boolean;
|
|
94
|
+
}
|
|
66
95
|
/** One successful login/registration: the bearer token plus the user. */
|
|
67
96
|
export interface QaAccountSession {
|
|
68
97
|
readonly token: string;
|
|
@@ -91,6 +120,90 @@ export interface QaOwnershipEntry {
|
|
|
91
120
|
readonly displayName: string;
|
|
92
121
|
readonly claimedAt: string;
|
|
93
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Why one skill draft cannot be saved, or why it saves with a caveat. Codes
|
|
125
|
+
* stay stable on the wire; the browser owns the Russian copy.
|
|
126
|
+
*/
|
|
127
|
+
export type QaSkillDiagnosticCode = "name-required" | "name-invalid" | "name-mismatch" | "description-required" | "description-too-long" | "when-to-use-too-long" | "field-type-invalid" | "invocation-never" | "invocation-invalid" | "invocation-legacy-key" | "allowed-tools-invalid" | "tool-name-invalid" | "tool-unavailable" | "tools-too-many" | "file-too-large" | "frontmatter-missing" | "skill-file-missing" | "frontmatter-invalid" | "unknown-field" | "resource-unsupported";
|
|
128
|
+
/** One finding about a skill file or an editor draft. */
|
|
129
|
+
export interface QaSkillDiagnostic {
|
|
130
|
+
readonly code: QaSkillDiagnosticCode;
|
|
131
|
+
readonly severity: "error" | "warning";
|
|
132
|
+
/** The editor field the message belongs to, or null for a file-wide one. */
|
|
133
|
+
readonly field: string | null;
|
|
134
|
+
/** The offending value: a tool name, a frontmatter key, a limit. */
|
|
135
|
+
readonly detail: string | null;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* A JSON-representable frontmatter value. The editor receives the preserved
|
|
139
|
+
* foreign fields verbatim over the Host bridge, which carries JSON only, so
|
|
140
|
+
* the parser drops anything a YAML document can hold but JSON cannot.
|
|
141
|
+
*/
|
|
142
|
+
export type QaSkillJsonValue = string | number | boolean | null | readonly QaSkillJsonValue[] | {
|
|
143
|
+
readonly [key: string]: QaSkillJsonValue;
|
|
144
|
+
};
|
|
145
|
+
/** One personal skill as the catalog list renders it. */
|
|
146
|
+
export interface QaSkillSummary {
|
|
147
|
+
readonly name: string;
|
|
148
|
+
readonly description: string;
|
|
149
|
+
readonly whenToUse: string | null;
|
|
150
|
+
readonly modelInvocable: boolean;
|
|
151
|
+
readonly userInvocable: boolean;
|
|
152
|
+
/** Declared tools, in canonical order; unknown ones included. */
|
|
153
|
+
readonly allowedTools: readonly string[];
|
|
154
|
+
/** Declared tools the current QA scope cannot use; still stored as declared. */
|
|
155
|
+
readonly unavailableTools: readonly string[];
|
|
156
|
+
/** Entries in the skill directory besides SKILL.md (references, assets, …). */
|
|
157
|
+
readonly resourceCount: number;
|
|
158
|
+
readonly valid: boolean;
|
|
159
|
+
readonly diagnostics: readonly QaSkillDiagnostic[];
|
|
160
|
+
readonly updatedAt: string | null;
|
|
161
|
+
/** sha256 of the stored bytes; an update must echo the revision it read. */
|
|
162
|
+
readonly revision: string;
|
|
163
|
+
}
|
|
164
|
+
/** One personal skill with everything the editor needs. */
|
|
165
|
+
export interface QaSkillDocument extends QaSkillSummary {
|
|
166
|
+
readonly body: string;
|
|
167
|
+
/** Frontmatter the editor preserves but does not own. */
|
|
168
|
+
readonly extraFrontmatter: Readonly<Record<string, QaSkillJsonValue>>;
|
|
169
|
+
/** Absolute SKILL.md path; rendered read-only for advanced users. */
|
|
170
|
+
readonly sourcePath: string;
|
|
171
|
+
/** The canonical file the serializer writes, built from the parsed content. */
|
|
172
|
+
readonly preview: string;
|
|
173
|
+
}
|
|
174
|
+
/** One tool the picker can offer, with this deployment's availability. */
|
|
175
|
+
export interface QaSkillToolDescriptor {
|
|
176
|
+
readonly name: string;
|
|
177
|
+
readonly description: string;
|
|
178
|
+
/** False when the QA session's own scope cannot use the tool. */
|
|
179
|
+
readonly available: boolean;
|
|
180
|
+
}
|
|
181
|
+
/** The editor's save payload. */
|
|
182
|
+
export interface QaSkillDraftInput {
|
|
183
|
+
readonly name: string;
|
|
184
|
+
readonly description: string;
|
|
185
|
+
readonly whenToUse: string | null;
|
|
186
|
+
readonly modelInvocable: boolean;
|
|
187
|
+
readonly userInvocable: boolean;
|
|
188
|
+
readonly allowedTools: readonly string[];
|
|
189
|
+
readonly body: string;
|
|
190
|
+
/** Echo of the revision the editor read; a stale one is refused. */
|
|
191
|
+
readonly expectedRevision: string | null;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* The Host's answer about one unsaved draft: the file a save would write and
|
|
195
|
+
* the diagnostics it found. The editor shows its own subset immediately and
|
|
196
|
+
* this authoritative set as soon as it arrives.
|
|
197
|
+
*/
|
|
198
|
+
export interface QaSkillValidation {
|
|
199
|
+
readonly preview: string;
|
|
200
|
+
readonly diagnostics: readonly QaSkillDiagnostic[];
|
|
201
|
+
}
|
|
202
|
+
/** What one delete did: v1 keeps the directory recoverable. */
|
|
203
|
+
export interface QaSkillRemoval {
|
|
204
|
+
readonly name: string;
|
|
205
|
+
readonly trashed: boolean;
|
|
206
|
+
}
|
|
94
207
|
export interface QaSourcesConfig {
|
|
95
208
|
readonly enabled?: boolean;
|
|
96
209
|
readonly collect?: {
|
|
@@ -174,6 +287,11 @@ export interface QaSurfaceConfig {
|
|
|
174
287
|
/** Floor for the visitor-resizable transcript/composer width; the page caps it. */
|
|
175
288
|
readonly minContentWidth?: number;
|
|
176
289
|
readonly showSessionList?: boolean;
|
|
290
|
+
/**
|
|
291
|
+
* Sign subagent completion notices with deterministic codenames
|
|
292
|
+
* («Дотошный Барсук») instead of the child's readable name or raw id.
|
|
293
|
+
*/
|
|
294
|
+
readonly subagentCodenames?: boolean;
|
|
177
295
|
};
|
|
178
296
|
readonly suggestedQuestions?: readonly string[];
|
|
179
297
|
/**
|
|
@@ -185,6 +303,27 @@ export interface QaSurfaceConfig {
|
|
|
185
303
|
readonly approvals?: QaApprovalInteraction;
|
|
186
304
|
readonly questions?: QaQuestionInteraction;
|
|
187
305
|
};
|
|
306
|
+
/**
|
|
307
|
+
* QA tool delivery. Dynamic activation keeps the QA tool schemas out of the
|
|
308
|
+
* model request until the activation skill has actually been loaded.
|
|
309
|
+
*/
|
|
310
|
+
readonly tools?: {
|
|
311
|
+
/**
|
|
312
|
+
* `true` attaches the QA tools only after the activation skill loads;
|
|
313
|
+
* `false` attaches them to every managed agent at creation.
|
|
314
|
+
*/
|
|
315
|
+
readonly dynamicActivation?: boolean;
|
|
316
|
+
/** The skill name whose successful load attaches the QA tools. */
|
|
317
|
+
readonly activationSkill?: string;
|
|
318
|
+
/** Accepted activation policy; only `all` is implemented. */
|
|
319
|
+
readonly activationMode?: QaToolActivationMode;
|
|
320
|
+
/**
|
|
321
|
+
* Agent presets whose sessions participate. An empty list leaves the gate
|
|
322
|
+
* open, which is only safe when this plugin serves one agent composition —
|
|
323
|
+
* name the QA preset in any deployment that composes more than one.
|
|
324
|
+
*/
|
|
325
|
+
readonly activationPresets?: readonly string[];
|
|
326
|
+
};
|
|
188
327
|
readonly lockdown?: {
|
|
189
328
|
readonly enabled?: boolean;
|
|
190
329
|
readonly enforceFixedAgentPreset?: boolean;
|
|
@@ -222,6 +361,20 @@ export interface QaSurfaceConfig {
|
|
|
222
361
|
* The child directory is not registered as a separate DSH workspace.
|
|
223
362
|
*/
|
|
224
363
|
readonly perUserWorkspace?: boolean;
|
|
364
|
+
/**
|
|
365
|
+
* Personal Skills: the user's own `.dsh/skills` below their QA workspace,
|
|
366
|
+
* surfaced through a skill provider this plugin owns.
|
|
367
|
+
*/
|
|
368
|
+
readonly skills?: {
|
|
369
|
+
readonly enabled?: boolean;
|
|
370
|
+
/** Directory below the personal root; relative, never escaping it. */
|
|
371
|
+
readonly relativeRoot?: string;
|
|
372
|
+
/** Follow manual file edits and refresh the DSH catalog. */
|
|
373
|
+
readonly watch?: boolean;
|
|
374
|
+
readonly maxSkillBytes?: number;
|
|
375
|
+
/** Reserved for the resource editor; v1 edits SKILL.md only. */
|
|
376
|
+
readonly allowResourceEditing?: boolean;
|
|
377
|
+
};
|
|
225
378
|
/** Self-declared profile: storage, the owner's form, and prompt injection. */
|
|
226
379
|
readonly profile?: {
|
|
227
380
|
readonly enabled?: boolean;
|
|
@@ -235,6 +388,10 @@ export interface QaSurfaceConfig {
|
|
|
235
388
|
/** Character cap on the user's free-form agent guidance. */
|
|
236
389
|
readonly instructionsMaxLength?: number;
|
|
237
390
|
};
|
|
391
|
+
/** Per-account starter buttons above an empty composer. */
|
|
392
|
+
readonly starters?: {
|
|
393
|
+
readonly enabled?: boolean;
|
|
394
|
+
};
|
|
238
395
|
};
|
|
239
396
|
readonly entry?: {
|
|
240
397
|
/** Inject the root → /qa redirect for non-loopback hostnames. */
|
|
@@ -244,6 +401,8 @@ export interface QaSurfaceConfig {
|
|
|
244
401
|
};
|
|
245
402
|
readonly sources?: QaSourcesConfig;
|
|
246
403
|
readonly attachments?: QaAttachmentsConfig;
|
|
404
|
+
/** Document pipeline: creation, conversion and extraction (see documents/). */
|
|
405
|
+
readonly documents?: QaDocumentsConfig;
|
|
247
406
|
}
|
|
248
407
|
/** What a QA visitor may attach to one message. */
|
|
249
408
|
export interface QaAttachmentsConfig {
|
|
@@ -299,6 +458,7 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
299
458
|
readonly renderMarkdown: boolean;
|
|
300
459
|
readonly minContentWidth: number;
|
|
301
460
|
readonly showSessionList: boolean;
|
|
461
|
+
readonly subagentCodenames: boolean;
|
|
302
462
|
};
|
|
303
463
|
readonly suggestedQuestions: readonly string[];
|
|
304
464
|
readonly thinkingPhrases: readonly string[];
|
|
@@ -342,11 +502,33 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
342
502
|
readonly identities: readonly QaAccountIdentityField[];
|
|
343
503
|
readonly instructionsMaxLength: number;
|
|
344
504
|
};
|
|
505
|
+
/** Per-account starter buttons above an empty composer. */
|
|
506
|
+
readonly starters: {
|
|
507
|
+
readonly enabled: boolean;
|
|
508
|
+
};
|
|
509
|
+
/**
|
|
510
|
+
* Personal Skills. Resolution turns the flag off on any deployment that
|
|
511
|
+
* cannot give every account its own directory: the storage root is the
|
|
512
|
+
* account's own workspace, so there is no safe shared fallback.
|
|
513
|
+
*/
|
|
514
|
+
skills: {
|
|
515
|
+
readonly enabled: boolean;
|
|
516
|
+
readonly relativeRoot: string;
|
|
517
|
+
readonly watch: boolean;
|
|
518
|
+
readonly maxSkillBytes: number;
|
|
519
|
+
readonly allowResourceEditing: boolean;
|
|
520
|
+
};
|
|
345
521
|
};
|
|
346
522
|
readonly entry: {
|
|
347
523
|
readonly redirectNonLoopback: boolean;
|
|
348
524
|
readonly cookieBootstrap: boolean;
|
|
349
525
|
};
|
|
526
|
+
readonly tools: {
|
|
527
|
+
readonly dynamicActivation: boolean;
|
|
528
|
+
readonly activationSkill: string;
|
|
529
|
+
readonly activationMode: QaToolActivationMode;
|
|
530
|
+
readonly activationPresets: readonly string[];
|
|
531
|
+
};
|
|
350
532
|
readonly sources: {
|
|
351
533
|
readonly enabled: boolean;
|
|
352
534
|
readonly collect: {
|
|
@@ -395,6 +577,7 @@ export interface ResolvedQaSurfaceConfig {
|
|
|
395
577
|
readonly maxPending: number;
|
|
396
578
|
readonly extensions: readonly string[];
|
|
397
579
|
};
|
|
580
|
+
readonly documents: ResolvedQaDocumentsConfig;
|
|
398
581
|
}
|
|
399
582
|
export interface QaSourceFilePreview {
|
|
400
583
|
readonly path: string;
|
|
@@ -417,11 +600,12 @@ export interface QaLockdownProof {
|
|
|
417
600
|
readonly toolPolicyLoaded: boolean;
|
|
418
601
|
readonly toolAllowList: readonly string[];
|
|
419
602
|
}
|
|
420
|
-
export
|
|
603
|
+
export interface QaUserMessage {
|
|
421
604
|
readonly id: string;
|
|
422
605
|
readonly role: "user";
|
|
423
606
|
readonly text: string;
|
|
424
|
-
|
|
607
|
+
/** `pending` is a browser-only optimistic row until the Host emits it. */
|
|
608
|
+
readonly status: "pending" | "committed";
|
|
425
609
|
readonly timestamp?: number;
|
|
426
610
|
readonly images?: readonly QaImageView[];
|
|
427
611
|
/** Durable files the user attached to this message, in prompt order. */
|
|
@@ -431,7 +615,12 @@ export type QaMessage = {
|
|
|
431
615
|
* chat; the owner themself sees their messages unlabeled.
|
|
432
616
|
*/
|
|
433
617
|
readonly author?: string;
|
|
434
|
-
}
|
|
618
|
+
}
|
|
619
|
+
/** Browser-only user row shown while the Host prepares the accepted turn. */
|
|
620
|
+
export type QaPendingUserMessage = Omit<QaUserMessage, "status"> & {
|
|
621
|
+
readonly status: "pending";
|
|
622
|
+
};
|
|
623
|
+
export type QaMessage = QaUserMessage | {
|
|
435
624
|
readonly id: string;
|
|
436
625
|
readonly role: "assistant";
|
|
437
626
|
readonly text: string;
|
|
@@ -462,6 +651,8 @@ export type QaMessage = {
|
|
|
462
651
|
readonly notice?: {
|
|
463
652
|
readonly title: string;
|
|
464
653
|
readonly body: string;
|
|
654
|
+
/** Muted correlation line above the body (task name, session id). */
|
|
655
|
+
readonly meta?: string;
|
|
465
656
|
};
|
|
466
657
|
} | {
|
|
467
658
|
readonly id: string;
|
|
@@ -528,6 +719,8 @@ export type QaAttachmentDraft = QaImageDraft | QaFileDraft;
|
|
|
528
719
|
export interface QaImageView {
|
|
529
720
|
readonly attachmentId: string;
|
|
530
721
|
readonly mediaType: QaImageMediaType;
|
|
722
|
+
/** Browser-local thumbnail URL, present only on an optimistic message. */
|
|
723
|
+
readonly previewUrl?: string;
|
|
531
724
|
}
|
|
532
725
|
/**
|
|
533
726
|
* A durable file attached to a sent message. The browser never reads these
|
|
@@ -592,7 +785,15 @@ export interface QaSessionState {
|
|
|
592
785
|
readonly phase: QaSessionPhase;
|
|
593
786
|
readonly sessionId: string | null;
|
|
594
787
|
readonly messages: readonly QaMessage[];
|
|
788
|
+
/** Immediate send feedback, kept outside the durable transcript. */
|
|
789
|
+
readonly pendingMessage: QaPendingUserMessage | null;
|
|
595
790
|
readonly error: string | null;
|
|
791
|
+
/**
|
|
792
|
+
* An owner-authorized historical chat whose recorded composition no longer
|
|
793
|
+
* matches the deployment. Its transcript remains visible, but no Host
|
|
794
|
+
* operation may be issued through this binding.
|
|
795
|
+
*/
|
|
796
|
+
readonly compatibilityReadOnly?: boolean;
|
|
596
797
|
readonly canSend: boolean;
|
|
597
798
|
readonly canStop: boolean;
|
|
598
799
|
/** Bumped whenever this browser's chat index changes (add/forget). */
|
|
@@ -608,4 +809,8 @@ export interface QaSessionState {
|
|
|
608
809
|
/** Question requests parked for the operator's answer, oldest first. */
|
|
609
810
|
readonly questions: readonly QaPendingQuestion[];
|
|
610
811
|
}
|
|
812
|
+
/** Minimal server-trusted identity exposed to principal-scoped plugins. */
|
|
813
|
+
export interface QaPrincipal {
|
|
814
|
+
readonly userId: string;
|
|
815
|
+
}
|
|
611
816
|
//# sourceMappingURL=types.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yadsh/dsh-qa-surface",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "A focused end-user QA surface backed by native DeepSeek Harness sessions",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"main": "./lib/index.js",
|
|
16
16
|
"types": "./lib/types/index.d.ts",
|
|
17
17
|
"bin": {
|
|
18
|
-
"qa-accounts": "./lib/cli.js"
|
|
18
|
+
"qa-accounts": "./lib/cli.js",
|
|
19
|
+
"qa-repair-sessions": "./scripts/repair-session-events.mjs"
|
|
19
20
|
},
|
|
20
21
|
"exports": {
|
|
21
22
|
".": {
|
|
@@ -26,6 +27,14 @@
|
|
|
26
27
|
"types": "./lib/types/client/index.d.ts",
|
|
27
28
|
"default": "./lib/client.js"
|
|
28
29
|
},
|
|
30
|
+
"./client/panels": {
|
|
31
|
+
"types": "./lib/types/client/panels/index.d.ts",
|
|
32
|
+
"default": "./lib/client/panels/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./client/settings": {
|
|
35
|
+
"types": "./lib/types/client/settings-extensions/index.d.ts",
|
|
36
|
+
"default": "./lib/client/settings-extensions/index.js"
|
|
37
|
+
},
|
|
29
38
|
"./remote": {
|
|
30
39
|
"types": "./lib/typert.remote-client.d.ts",
|
|
31
40
|
"default": "./lib/typert.remote-client.js"
|
|
@@ -66,6 +75,7 @@
|
|
|
66
75
|
"lib/**/*.js",
|
|
67
76
|
"lib/**/*.js.map",
|
|
68
77
|
"lib/**/*.d.ts",
|
|
78
|
+
"scripts/repair-session-events.mjs",
|
|
69
79
|
"cordis.patch.yml",
|
|
70
80
|
"compatibility.json",
|
|
71
81
|
"capability-policy.json",
|
|
@@ -110,6 +120,7 @@
|
|
|
110
120
|
"@deepseek-ai/dsh-permission-presets": ">=0.1.5-rc.2 <0.2.0",
|
|
111
121
|
"@deepseek-ai/dsh-session": ">=0.1.5-rc.2 <0.2.0",
|
|
112
122
|
"@deepseek-ai/dsh-settings": ">=0.1.5-rc.2 <0.2.0",
|
|
123
|
+
"@deepseek-ai/dsh-skill": ">=0.1.5-rc.2 <0.2.0",
|
|
113
124
|
"@deepseek-ai/dsh-system-prompt": ">=0.1.5-rc.2 <0.2.0",
|
|
114
125
|
"@deepseek-ai/dsh-tools": ">=0.1.5-rc.2 <0.2.0",
|
|
115
126
|
"@deepseek-ai/dsh-typert-protocol": ">=0.1.5-rc.2 <0.2.0",
|
|
@@ -118,8 +129,9 @@
|
|
|
118
129
|
"react-dom": "^18.2.0"
|
|
119
130
|
},
|
|
120
131
|
"dependencies": {
|
|
132
|
+
"yaml": "^2.9.0",
|
|
121
133
|
"zod": "^4.4.3",
|
|
122
|
-
"@yadsh/dsh-plugin-log": "^0.3.
|
|
134
|
+
"@yadsh/dsh-plugin-log": "^0.3.1"
|
|
123
135
|
},
|
|
124
136
|
"devDependencies": {
|
|
125
137
|
"@deepseek-ai/cordis": "4.0.2",
|
|
@@ -141,8 +153,10 @@
|
|
|
141
153
|
"@deepseek-ai/dsh-host-webserver": "0.1.5-rc.2",
|
|
142
154
|
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
143
155
|
"@deepseek-ai/dsh-permission-presets": "0.1.5-rc.2",
|
|
156
|
+
"@deepseek-ai/dsh-scope": "0.1.5-rc.2",
|
|
144
157
|
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
|
|
145
158
|
"@deepseek-ai/dsh-settings": "0.1.5-rc.2",
|
|
159
|
+
"@deepseek-ai/dsh-skill": "0.1.5-rc.2",
|
|
146
160
|
"@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2",
|
|
147
161
|
"@deepseek-ai/dsh-tools": "0.1.5-rc.2",
|
|
148
162
|
"@deepseek-ai/dsh-typert-generator": "0.1.5-rc.2",
|
|
@@ -155,7 +169,6 @@
|
|
|
155
169
|
"eslint": "10.9.1",
|
|
156
170
|
"jsdom": "^26.1.0",
|
|
157
171
|
"playwright": "1.62.1",
|
|
158
|
-
"prettier": "^3.6.2",
|
|
159
172
|
"react": "18.3.1",
|
|
160
173
|
"react-dom": "18.3.1",
|
|
161
174
|
"tsdown": "^0.22.14",
|
|
@@ -171,15 +184,15 @@
|
|
|
171
184
|
},
|
|
172
185
|
"scripts": {
|
|
173
186
|
"clean": "node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\"",
|
|
174
|
-
"build": "pnpm run
|
|
187
|
+
"build": "pnpm run clean && node scripts/generate-typert.mjs && tsc -p tsconfig.build.json && tsdown",
|
|
175
188
|
"lint": "eslint src tests scripts tsdown.config.ts",
|
|
176
|
-
"format": "prettier --check . --end-of-line auto",
|
|
177
|
-
"format:write": "prettier --write . --end-of-line auto",
|
|
178
189
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
179
190
|
"test": "vitest run",
|
|
180
|
-
"verify": "node scripts/verify-package.mjs",
|
|
191
|
+
"verify:package": "node scripts/verify-package.mjs",
|
|
192
|
+
"verify": "pnpm run verify:package && pnpm run verify:consumer",
|
|
193
|
+
"verify:consumer": "tsc -p scripts/fixtures/tsconfig.json --noEmit",
|
|
181
194
|
"smoke:packed": "node scripts/smoke-packed-dsh.mjs",
|
|
182
195
|
"e2e:browser": "node scripts/smoke-packed-dsh.mjs --browser",
|
|
183
|
-
"check": "pnpm run
|
|
196
|
+
"check": "pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run build && pnpm run verify"
|
|
184
197
|
}
|
|
185
198
|
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
chmodSync,
|
|
5
|
+
copyFileSync,
|
|
6
|
+
constants as fsConstants,
|
|
7
|
+
lstatSync,
|
|
8
|
+
readFileSync,
|
|
9
|
+
readdirSync,
|
|
10
|
+
renameSync,
|
|
11
|
+
statSync,
|
|
12
|
+
writeFileSync,
|
|
13
|
+
} from "node:fs";
|
|
14
|
+
import os from "node:os";
|
|
15
|
+
import path from "node:path";
|
|
16
|
+
import { pathToFileURL } from "node:url";
|
|
17
|
+
import {
|
|
18
|
+
constants as zlibConstants,
|
|
19
|
+
zstdCompressSync,
|
|
20
|
+
zstdDecompressSync,
|
|
21
|
+
} from "node:zlib";
|
|
22
|
+
|
|
23
|
+
export const REPAIRABLE_EVENT_TYPES = new Set([
|
|
24
|
+
"safety-gate/check",
|
|
25
|
+
"safety-gate/block",
|
|
26
|
+
"safety-gate/warn",
|
|
27
|
+
"safety-gate/classifier-error",
|
|
28
|
+
"qa/sources",
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
const ZSTD_MAGIC = 0xfd2fb528;
|
|
32
|
+
const CHECKSUM_OPTIONS = {
|
|
33
|
+
params: { [zlibConstants.ZSTD_c_checksumFlag]: 1 },
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** Locate complete frames in a concatenated Zstandard artifact. */
|
|
37
|
+
export function scanZstdFrames(buffer) {
|
|
38
|
+
const frames = [];
|
|
39
|
+
let offset = 0;
|
|
40
|
+
while (offset < buffer.length) {
|
|
41
|
+
const start = offset;
|
|
42
|
+
if (buffer.length - offset < 5) throw new Error(`torn frame at ${start}`);
|
|
43
|
+
if (buffer.readUInt32LE(offset) !== ZSTD_MAGIC) {
|
|
44
|
+
throw new Error(`bad Zstandard magic at ${offset}`);
|
|
45
|
+
}
|
|
46
|
+
offset += 4;
|
|
47
|
+
const descriptor = buffer.readUInt8(offset);
|
|
48
|
+
offset += 1;
|
|
49
|
+
const contentSizeFlag = descriptor >>> 6;
|
|
50
|
+
const singleSegment = (descriptor & 32) !== 0;
|
|
51
|
+
const checksum = (descriptor & 4) !== 0;
|
|
52
|
+
const dictionaryFlag = descriptor & 3;
|
|
53
|
+
const dictionaryBytes = dictionaryFlag === 3 ? 4 : dictionaryFlag;
|
|
54
|
+
const contentSizeBytes =
|
|
55
|
+
contentSizeFlag === 0 ? (singleSegment ? 1 : 0) : 1 << contentSizeFlag;
|
|
56
|
+
const headerBytes =
|
|
57
|
+
(singleSegment ? 0 : 1) + dictionaryBytes + contentSizeBytes;
|
|
58
|
+
if (buffer.length - offset < headerBytes) {
|
|
59
|
+
throw new Error(`torn frame header at ${start}`);
|
|
60
|
+
}
|
|
61
|
+
offset += headerBytes;
|
|
62
|
+
for (;;) {
|
|
63
|
+
if (buffer.length - offset < 3) {
|
|
64
|
+
throw new Error(`torn block header at ${start}`);
|
|
65
|
+
}
|
|
66
|
+
const blockHeader = buffer.readUIntLE(offset, 3);
|
|
67
|
+
offset += 3;
|
|
68
|
+
const lastBlock = (blockHeader & 1) !== 0;
|
|
69
|
+
const blockType = (blockHeader >>> 1) & 3;
|
|
70
|
+
const blockSize = blockHeader >>> 3;
|
|
71
|
+
if (blockType === 3) throw new Error(`reserved block type at ${start}`);
|
|
72
|
+
const payloadBytes = blockType === 1 ? 1 : blockSize;
|
|
73
|
+
if (buffer.length - offset < payloadBytes) {
|
|
74
|
+
throw new Error(`torn block payload at ${start}`);
|
|
75
|
+
}
|
|
76
|
+
offset += payloadBytes;
|
|
77
|
+
if (lastBlock) break;
|
|
78
|
+
}
|
|
79
|
+
if (checksum) {
|
|
80
|
+
if (buffer.length - offset < 4) {
|
|
81
|
+
throw new Error(`torn checksum at ${start}`);
|
|
82
|
+
}
|
|
83
|
+
offset += 4;
|
|
84
|
+
}
|
|
85
|
+
frames.push({ start, end: offset });
|
|
86
|
+
}
|
|
87
|
+
return frames;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function decodeArtifact(filePath, content) {
|
|
91
|
+
if (!filePath.endsWith(".zstd")) return content.toString("utf8");
|
|
92
|
+
return scanZstdFrames(content)
|
|
93
|
+
.map(({ start, end }) =>
|
|
94
|
+
zstdDecompressSync(content.subarray(start, end)).toString("utf8"),
|
|
95
|
+
)
|
|
96
|
+
.join("");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function encodeArtifact(filePath, rows) {
|
|
100
|
+
const text = `${rows.map((row) => JSON.stringify(row)).join("\n")}\n`;
|
|
101
|
+
if (!filePath.endsWith(".zstd")) return Buffer.from(text, "utf8");
|
|
102
|
+
// Harness requires the first frame to contain exactly the header line.
|
|
103
|
+
const frames = [
|
|
104
|
+
zstdCompressSync(
|
|
105
|
+
Buffer.from(`${JSON.stringify(rows[0])}\n`, "utf8"),
|
|
106
|
+
CHECKSUM_OPTIONS,
|
|
107
|
+
),
|
|
108
|
+
];
|
|
109
|
+
const eventRows = rows.slice(1);
|
|
110
|
+
const frameSize = 2_000;
|
|
111
|
+
for (let index = 0; index < eventRows.length; index += frameSize) {
|
|
112
|
+
const plain = `${eventRows
|
|
113
|
+
.slice(index, index + frameSize)
|
|
114
|
+
.map((row) => JSON.stringify(row))
|
|
115
|
+
.join("\n")}\n`;
|
|
116
|
+
frames.push(zstdCompressSync(Buffer.from(plain, "utf8"), CHECKSUM_OPTIONS));
|
|
117
|
+
}
|
|
118
|
+
return Buffer.concat(frames);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function parseRows(filePath, plain) {
|
|
122
|
+
const lines = plain.split("\n").filter((line) => line.length > 0);
|
|
123
|
+
if (lines.length === 0) throw new Error(`${filePath}: empty session log`);
|
|
124
|
+
return lines.map((line, index) => {
|
|
125
|
+
try {
|
|
126
|
+
const row = JSON.parse(line);
|
|
127
|
+
if (typeof row !== "object" || row === null || Array.isArray(row)) {
|
|
128
|
+
throw new Error("row is not an object");
|
|
129
|
+
}
|
|
130
|
+
return row;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
throw new Error(`${filePath}: invalid JSON on row ${index + 1}`, {
|
|
133
|
+
cause: error,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Repair one offline session log; dry-run is the default. */
|
|
140
|
+
export function repairSessionFile(filePath, options = {}) {
|
|
141
|
+
const write = options.write === true;
|
|
142
|
+
const before = statSync(filePath);
|
|
143
|
+
const original = readFileSync(filePath);
|
|
144
|
+
const rows = parseRows(filePath, decodeArtifact(filePath, original));
|
|
145
|
+
let changed = 0;
|
|
146
|
+
const types = new Map();
|
|
147
|
+
for (let index = 1; index < rows.length; index += 1) {
|
|
148
|
+
const row = rows[index];
|
|
149
|
+
if (!REPAIRABLE_EVENT_TYPES.has(row.type) || row.ignorable === true)
|
|
150
|
+
continue;
|
|
151
|
+
row.ignorable = true;
|
|
152
|
+
changed += 1;
|
|
153
|
+
types.set(row.type, (types.get(row.type) ?? 0) + 1);
|
|
154
|
+
}
|
|
155
|
+
if (changed === 0 || !write) {
|
|
156
|
+
return {
|
|
157
|
+
filePath,
|
|
158
|
+
changed,
|
|
159
|
+
types: Object.fromEntries(types),
|
|
160
|
+
written: false,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const now = statSync(filePath);
|
|
165
|
+
if (now.size !== before.size || now.mtimeMs !== before.mtimeMs) {
|
|
166
|
+
throw new Error(
|
|
167
|
+
`${filePath}: changed while being inspected; stop DSH and retry`,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
const backup = `${filePath}.pre-plugin-event-repair.bak`;
|
|
171
|
+
copyFileSync(filePath, backup, fsConstants.COPYFILE_EXCL);
|
|
172
|
+
const repaired = encodeArtifact(filePath, rows);
|
|
173
|
+
// Decode before publishing so a bad generated frame cannot replace the log.
|
|
174
|
+
parseRows(filePath, decodeArtifact(filePath, repaired));
|
|
175
|
+
const temp = `${filePath}.${process.pid}.repair.tmp`;
|
|
176
|
+
writeFileSync(temp, repaired, { mode: before.mode });
|
|
177
|
+
chmodSync(temp, before.mode);
|
|
178
|
+
renameSync(temp, filePath);
|
|
179
|
+
return {
|
|
180
|
+
filePath,
|
|
181
|
+
changed,
|
|
182
|
+
types: Object.fromEntries(types),
|
|
183
|
+
written: true,
|
|
184
|
+
backup,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function sessionFiles(target) {
|
|
189
|
+
const details = lstatSync(target);
|
|
190
|
+
if (details.isSymbolicLink()) return [];
|
|
191
|
+
if (details.isFile()) {
|
|
192
|
+
return target.endsWith(".jsonl") || target.endsWith(".jsonl.zstd")
|
|
193
|
+
? [target]
|
|
194
|
+
: [];
|
|
195
|
+
}
|
|
196
|
+
if (!details.isDirectory()) return [];
|
|
197
|
+
return readdirSync(target, { withFileTypes: true }).flatMap((entry) => {
|
|
198
|
+
if (entry.isSymbolicLink()) return [];
|
|
199
|
+
return sessionFiles(path.join(target, entry.name));
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function usage() {
|
|
204
|
+
return `Usage: qa-repair-sessions [--write] [session-file-or-directory ...]
|
|
205
|
+
|
|
206
|
+
Dry-run is the default. With no target, scans $DSH_HOME/sessions (or
|
|
207
|
+
~/.dsh/sessions when DSH_HOME is unset). Stop DSH before using --write.
|
|
208
|
+
|
|
209
|
+
The command only adds ignorable:true to legacy safety-gate/* and qa/sources
|
|
210
|
+
events. Before each changed file is replaced atomically, an exclusive
|
|
211
|
+
*.pre-plugin-event-repair.bak backup is created.`;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function main(argv = process.argv.slice(2)) {
|
|
215
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
216
|
+
console.log(usage());
|
|
217
|
+
return 0;
|
|
218
|
+
}
|
|
219
|
+
const write = argv.includes("--write");
|
|
220
|
+
const unknown = argv.filter(
|
|
221
|
+
(arg) => arg.startsWith("-") && arg !== "--write",
|
|
222
|
+
);
|
|
223
|
+
if (unknown.length > 0) throw new Error(`unknown option: ${unknown[0]}`);
|
|
224
|
+
const targets = argv.filter((arg) => !arg.startsWith("-"));
|
|
225
|
+
if (targets.length === 0) {
|
|
226
|
+
const home =
|
|
227
|
+
process.env.DSH_HOME?.trim() || path.join(os.homedir(), ".dsh");
|
|
228
|
+
targets.push(path.join(home, "sessions"));
|
|
229
|
+
}
|
|
230
|
+
if (write) console.error("write mode: DSH must be stopped");
|
|
231
|
+
const files = [...new Set(targets.flatMap(sessionFiles))].sort();
|
|
232
|
+
let candidates = 0;
|
|
233
|
+
let events = 0;
|
|
234
|
+
for (const file of files) {
|
|
235
|
+
const result = repairSessionFile(file, { write });
|
|
236
|
+
if (result.changed === 0) continue;
|
|
237
|
+
candidates += 1;
|
|
238
|
+
events += result.changed;
|
|
239
|
+
console.log(
|
|
240
|
+
`${result.written ? "repaired" : "would repair"}: ${file} (${result.changed} events)`,
|
|
241
|
+
);
|
|
242
|
+
if (result.backup !== undefined) console.log(`backup: ${result.backup}`);
|
|
243
|
+
}
|
|
244
|
+
console.log(
|
|
245
|
+
`${write ? "repaired" : "dry run"}: ${events} events in ${candidates} of ${files.length} session logs`,
|
|
246
|
+
);
|
|
247
|
+
return 0;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (
|
|
251
|
+
process.argv[1] !== undefined &&
|
|
252
|
+
pathToFileURL(path.resolve(process.argv[1])).href === import.meta.url
|
|
253
|
+
) {
|
|
254
|
+
try {
|
|
255
|
+
process.exitCode = main();
|
|
256
|
+
} catch (error) {
|
|
257
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
258
|
+
process.exitCode = 1;
|
|
259
|
+
}
|
|
260
|
+
}
|