@piagent/platform 1.37.1 → 1.38.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/CHANGELOG.md +47 -0
- package/README.md +5 -3
- package/README.vi.md +2 -2
- package/catalog/capabilities.json +2 -2
- package/docs/command-reference-vietnamese.md +4 -3
- package/docs/distribution-standard.md +6 -6
- package/docs/en/maintainer-guide.md +8 -0
- package/docs/en/workspace-editor.md +222 -0
- package/docs/languages.json +13 -4
- package/docs/operator-manual-vietnamese.md +7 -7
- package/docs/publishing-for-teams.md +2 -0
- package/docs/release-install-policy.md +2 -2
- package/docs/research/ide-m0-spike.md +101 -0
- package/docs/team-onboarding.md +2 -2
- package/docs/vi/maintainer-guide.md +8 -0
- package/docs/vi/workspace-editor.md +217 -0
- package/docs-site/architecture.html +1 -1
- package/docs-site/benchmark.html +1 -1
- package/docs-site/commands.html +1 -1
- package/docs-site/content/en/index.html +4 -4
- package/docs-site/content/en/whats-new.html +17 -0
- package/docs-site/content/index.html +4 -4
- package/docs-site/content/whats-new.html +17 -0
- package/docs-site/context-engine.html +1 -1
- package/docs-site/ecosystem.html +1 -1
- package/docs-site/en/architecture.html +1 -1
- package/docs-site/en/benchmark.html +1 -1
- package/docs-site/en/commands.html +1 -1
- package/docs-site/en/context-engine.html +1 -1
- package/docs-site/en/ecosystem.html +1 -1
- package/docs-site/en/index.html +5 -5
- package/docs-site/en/mcp-approval.html +1 -1
- package/docs-site/en/mcp-auth.html +1 -1
- package/docs-site/en/mcp-servers.html +1 -1
- package/docs-site/en/mcp.html +1 -1
- package/docs-site/en/permissions.html +1 -1
- package/docs-site/en/profiles.html +1 -1
- package/docs-site/en/quickstart.html +1 -1
- package/docs-site/en/runtime.html +1 -1
- package/docs-site/en/scope.html +1 -1
- package/docs-site/en/security.html +1 -1
- package/docs-site/en/team.html +1 -1
- package/docs-site/en/whats-new.html +18 -1
- package/docs-site/en/windows.html +1 -1
- package/docs-site/en/workflows.html +1 -1
- package/docs-site/index.html +5 -5
- package/docs-site/mcp-approval.html +1 -1
- package/docs-site/mcp-auth.html +1 -1
- package/docs-site/mcp-servers.html +1 -1
- package/docs-site/mcp.html +1 -1
- package/docs-site/permissions.html +1 -1
- package/docs-site/profiles.html +1 -1
- package/docs-site/quickstart.html +1 -1
- package/docs-site/runtime.html +1 -1
- package/docs-site/scope.html +1 -1
- package/docs-site/security.html +1 -1
- package/docs-site/team.html +1 -1
- package/docs-site/whats-new.html +18 -1
- package/docs-site/windows.html +1 -1
- package/docs-site/workflows.html +1 -1
- package/evals/fixtures/piagent-webui/checkpoint-v1.invalid.json +21 -0
- package/evals/fixtures/piagent-webui/checkpoint-v1.valid.json +20 -0
- package/evals/fixtures/piagent-webui/terminal-v1.invalid.json +17 -0
- package/evals/fixtures/piagent-webui/terminal-v1.valid.json +16 -0
- package/evals/fixtures/piagent-webui/workspace-file-v1.invalid.json +24 -0
- package/evals/fixtures/piagent-webui/workspace-file-v1.valid.json +23 -0
- package/evals/fixtures/piagent-webui/workspace-paths-v1.invalid.json +24 -0
- package/evals/fixtures/piagent-webui/workspace-paths-v1.valid.json +24 -0
- package/evals/fixtures/piagent-webui/workspace-search-v1.invalid.json +26 -0
- package/evals/fixtures/piagent-webui/workspace-search-v1.valid.json +26 -0
- package/evals/fixtures/piagent-webui/workspace-tree-v1.invalid.json +28 -0
- package/evals/fixtures/piagent-webui/workspace-tree-v1.valid.json +27 -0
- package/evals/fixtures/piagent-webui/workspace-write-v1.invalid.json +19 -0
- package/evals/fixtures/piagent-webui/workspace-write-v1.valid.json +19 -0
- package/evals/long-task-soak-v1/README.md +17 -0
- package/evals/long-task-soak-v1/lib/session-loop.mjs +19 -3
- package/evals/long-task-soak-v1/scenarios/ide-editor-terminal.json +19 -0
- package/evals/long-task-soak-v1/surfaces/webui-gateway.mjs +17 -2
- package/evals/long-task-soak-v1/surfaces/workspace-actions.mjs +95 -0
- package/evals/private-holdout-v1/public-exposure.v2.json +2 -2
- package/package.json +7 -3
- package/packages/piagent-core/extensions/fallback-base-policy.ts +1 -1
- package/packages/piagent-core/extensions/guard-types.ts +3 -1
- package/packages/piagent-core/extensions/path-suggestions.ts +137 -0
- package/packages/piagent-core/extensions/piagent-guard.ts +85 -7
- package/packages/piagent-core/extensions/workspace-inspection.ts +145 -0
- package/packages/piagent-core/extensions/workspace-policy.d.ts +7 -0
- package/packages/piagent-core/extensions/workspace-policy.js +3 -0
- package/packages/piagent-core/extensions/workspace-search-index.mjs +8 -0
- package/packages/piagent-core/extensions/workspace-search.ts +74 -0
- package/packages/piagent-core/extensions/workspace-write.ts +116 -0
- package/packages/piagent-core/managed/background-process.mjs +9 -4
- package/packages/piagent-core/managed/boundary-package-proxy.mjs +21 -0
- package/packages/piagent-core/managed/boundary-queue.mjs +24 -0
- package/packages/piagent-core/managed/checkpoint-git.mjs +16 -0
- package/packages/piagent-core/managed/checkpoints.mjs +17 -64
- package/packages/piagent-core/managed/command-tools.mjs +6 -6
- package/packages/piagent-core/managed/continuation.mjs +3 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/backend-api/profile.json +88 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/be-readonly-fe/profile.json +130 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/data/profile.json +88 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/devops/profile.json +90 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/docs/profile.json +74 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/fullstack/profile.json +92 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/generic/profile.json +95 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/mobile/profile.json +86 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/node-typescript/profile.json +74 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/python/profile.json +75 -0
- package/packages/piagent-core/managed/dist/workspace/assets/adapters/web-frontend/profile.json +99 -0
- package/packages/piagent-core/managed/dist/workspace/assets/local-state-path-BrmghxEZ.js +284 -0
- package/packages/piagent-core/managed/dist/workspace/assets/packages/piagent-core/policies/base-policy.json +351 -0
- package/packages/piagent-core/managed/dist/workspace/manifest.json +65 -0
- package/packages/piagent-core/managed/dist/workspace/worker.mjs +7374 -0
- package/packages/piagent-core/managed/dist/workspace/workspace-search-index.mjs +1007 -0
- package/packages/piagent-core/managed/patch-snapshot.mjs +6 -8
- package/packages/piagent-core/managed/permission.mjs +29 -6
- package/packages/piagent-core/managed/repository-operation.mjs +2 -1
- package/packages/piagent-core/managed/review-snapshot-request.mjs +21 -0
- package/packages/piagent-core/managed/sandbox-diagnostic.mjs +2 -0
- package/packages/piagent-core/managed/session-mutation-observations.mjs +37 -0
- package/packages/piagent-core/managed/session.mjs +2 -2
- package/packages/piagent-core/managed/source-revert-requests.mjs +21 -0
- package/packages/piagent-core/managed/terminal-boundary.mjs +88 -0
- package/packages/piagent-core/managed/terminal-channel.mjs +66 -0
- package/packages/piagent-core/managed/terminal-runtime.mjs +64 -0
- package/packages/piagent-core/managed/terminal-seatbelt.mjs +48 -0
- package/packages/piagent-core/managed/terminal-worker.mjs +70 -0
- package/packages/piagent-core/managed/tool-boundary.mjs +45 -35
- package/packages/piagent-core/managed/tool-freshness.mjs +47 -0
- package/packages/piagent-core/managed/tool-worker.mjs +18 -3
- package/packages/piagent-core/managed/workspace-worker-pins.mjs +26 -0
- package/packages/piagent-core/package.json +1 -1
- package/packages/piagent-core/policies/base-policy.json +2 -1
- package/packages/piagent-core/runtime/checkpoints/checkpoint-authority.ts +43 -0
- package/packages/piagent-core/runtime/checkpoints/checkpoint-refs.mjs +51 -0
- package/packages/piagent-core/runtime/checkpoints/checkpoint-store.mjs +179 -0
- package/packages/piagent-core/runtime/checkpoints/checkpoint-worker.ts +28 -0
- package/packages/piagent-core/runtime/checkpoints/git-adapter.mjs +36 -0
- package/packages/piagent-core/runtime/checkpoints/persistent-history.mjs +96 -0
- package/packages/piagent-core/runtime/checkpoints/personal-git.ts +272 -0
- package/packages/piagent-core/runtime/checkpoints/personal-runtime.ts +158 -0
- package/packages/piagent-core/runtime/checkpoints/prune.mjs +29 -0
- package/packages/piagent-core/runtime/checkpoints/restore-preview.mjs +46 -0
- package/packages/piagent-core/runtime/checkpoints/turn-checkpoints.mjs +167 -0
- package/packages/piagent-core/runtime/hooks/session-hooks.ts +19 -16
- package/packages/piagent-core/runtime/hooks/session-start-hook.ts +3 -0
- package/packages/piagent-core/runtime/hooks/tool-call-hook.ts +2 -2
- package/packages/piagent-core/runtime/inspection/diff-projection.ts +2 -1
- package/packages/piagent-core/runtime/inspection/managed-source-revert.ts +90 -0
- package/packages/piagent-core/runtime/inspection/review-state-projection.ts +19 -8
- package/packages/piagent-core/runtime/inspection/session-diff-projection.ts +47 -0
- package/packages/piagent-core/runtime/inspection/session-hunk-provenance.ts +56 -0
- package/packages/piagent-core/runtime/inspection/session-mutation-observer.ts +125 -0
- package/packages/piagent-core/runtime/inspection/source-action-contract.ts +123 -0
- package/packages/piagent-core/runtime/inspection/source-change-projection.ts +3 -9
- package/packages/piagent-core/runtime/inspection/source-mutation-projection.ts +3 -41
- package/packages/piagent-core/runtime/inspection/source-mutation-store.ts +6 -36
- package/packages/piagent-core/runtime/inspection/source-revert-projection.ts +36 -30
- package/packages/piagent-core/runtime/inspection/text-diff.ts +5 -4
- package/packages/piagent-core/runtime/inspection/workspace-worker.ts +79 -0
- package/packages/piagent-core/runtime/policy/source-index-transaction.ts +3 -10
- package/packages/piagent-core/runtime/policy/source-mutation-guard-binding.ts +27 -2
- package/packages/piagent-core/runtime/policy/source-mutation-guard.ts +42 -12
- package/packages/piagent-core/runtime/policy/source-worktree-transaction.ts +10 -5
- package/packages/piagent-core/runtime/policy/workspace-write-authority.ts +51 -0
- package/packages/piagent-core/runtime/process-owner.mjs +20 -0
- package/packages/piagent-core/runtime/process-tree-watch.mjs +46 -0
- package/packages/piagent-core/runtime/quality/model-mutation-proof.ts +8 -5
- package/packages/piagent-core/runtime/registration/permission-commands.ts +10 -2
- package/packages/piagent-core/runtime/registration/task-evidence-tools.ts +1 -1
- package/packages/piagent-core/runtime/session/workspace-member-edits.d.mts +7 -0
- package/packages/piagent-core/runtime/session/workspace-member-edits.mjs +41 -0
- package/packages/piagent-core/security/workspace-file-reader.ts +2 -1
- package/packages/piagent-webui/dist/client/assets/Alert-DXF8-XqE.js +1 -0
- package/packages/piagent-webui/dist/client/assets/Button-DZJosXQi.js +1 -0
- package/packages/piagent-webui/dist/client/assets/DialogTitle-CL-fzCnT.js +3 -0
- package/packages/piagent-webui/dist/client/assets/MarkdownMessage-k4tq1y8s.js +29 -0
- package/packages/piagent-webui/dist/client/assets/TerminalPanel-DvOPgrGI.js +2 -0
- package/packages/piagent-webui/dist/client/assets/TerminalView-B_a16moC.js +9 -0
- package/packages/piagent-webui/dist/client/assets/TerminalView-kHJ-D0s7.css +1 -0
- package/packages/piagent-webui/dist/client/assets/Typography-DMZL1kLS.js +1 -0
- package/packages/piagent-webui/dist/client/assets/WorkspaceCodeEditor-BCiYM9NA.js +2 -0
- package/packages/piagent-webui/dist/client/assets/WorkspaceExplorer-DttpQtpf.js +5 -0
- package/packages/piagent-webui/dist/client/assets/WorkspaceQuickOpen-fgXwQ46B.js +1 -0
- package/packages/piagent-webui/dist/client/assets/bootstrap-CedkNtRG.js +1 -0
- package/packages/piagent-webui/dist/client/assets/dist-B1M7IjfA.js +10 -0
- package/packages/piagent-webui/dist/client/assets/dist-BUYtGaUP.js +1 -0
- package/packages/piagent-webui/dist/client/assets/dist-C82AtDDT.js +6 -0
- package/packages/piagent-webui/dist/client/assets/dist-D9b8j6pJ.js +1 -0
- package/packages/piagent-webui/dist/client/assets/dist-DLfpWwLs.js +23 -0
- package/packages/piagent-webui/dist/client/assets/dist-DcEu_WYV.js +1 -0
- package/packages/piagent-webui/dist/client/assets/dist-_JsfplOG.js +9 -0
- package/packages/piagent-webui/dist/client/assets/dist-idN8f9Fc.js +1 -0
- package/packages/piagent-webui/dist/client/assets/dist-nvgpa2Us.js +1 -0
- package/packages/piagent-webui/dist/client/assets/index-BW8-BUMx.js +102 -0
- package/packages/piagent-webui/dist/client/assets/index-Brs_HjIo.css +1 -0
- package/packages/piagent-webui/dist/client/assets/rolldown-runtime-hePW80VL.js +1 -0
- package/packages/piagent-webui/dist/client/assets/tab-close-HE0XxoJf.js +1 -0
- package/packages/piagent-webui/dist/client/assets/ui-preferences-DiddStu0.js +124 -0
- package/packages/piagent-webui/dist/client/assets/useTheme-_ESOj7MI.js +10 -0
- package/packages/piagent-webui/dist/client/assets/workspace-api-O7auv_td.js +1 -0
- package/packages/piagent-webui/dist/client/index.html +10 -2
- package/packages/piagent-webui/extension/same-session-bridge.ts +2 -3
- package/packages/piagent-webui/extension/source-revert-controller.ts +14 -208
- package/packages/piagent-webui/gateway/checkpoint-sessions.ts +99 -0
- package/packages/piagent-webui/gateway/checkpoint-store.ts +6 -0
- package/packages/piagent-webui/gateway/company-relay.ts +5 -0
- package/packages/piagent-webui/gateway/company-terminal-cache.ts +54 -0
- package/packages/piagent-webui/gateway/company-terminal-channel.ts +117 -0
- package/packages/piagent-webui/gateway/company-terminal-relay.ts +75 -0
- package/packages/piagent-webui/gateway/gateway-protocol-service.ts +12 -0
- package/packages/piagent-webui/gateway/gateway-service.ts +48 -4
- package/packages/piagent-webui/gateway/managed-gateway.mjs +30 -3
- package/packages/piagent-webui/gateway/managed-projection.ts +5 -3
- package/packages/piagent-webui/gateway/managed-source-revert-controller.ts +45 -0
- package/packages/piagent-webui/gateway/managed-source-revert-sessions.ts +74 -0
- package/packages/piagent-webui/gateway/managed-terminal-binding.ts +30 -0
- package/packages/piagent-webui/gateway/managed-terminal-processes.ts +74 -0
- package/packages/piagent-webui/gateway/managed-terminal-sessions.ts +9 -0
- package/packages/piagent-webui/gateway/path-suggestions.ts +1 -124
- package/packages/piagent-webui/gateway/personal-terminal-binding.ts +36 -0
- package/packages/piagent-webui/gateway/personal-terminal-diagnostic.mjs +16 -0
- package/packages/piagent-webui/gateway/personal-terminal-processes.ts +119 -0
- package/packages/piagent-webui/gateway/personal-terminal-sessions.ts +22 -0
- package/packages/piagent-webui/gateway/runtime-session-controls.ts +2 -1
- package/packages/piagent-webui/gateway/session-catalog.ts +3 -2
- package/packages/piagent-webui/gateway/session-command-controller.ts +4 -4
- package/packages/piagent-webui/gateway/session-inspection-registry.ts +29 -5
- package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +8 -8
- package/packages/piagent-webui/gateway/signed-session-journal.ts +77 -0
- package/packages/piagent-webui/gateway/source-revert-sessions.ts +74 -0
- package/packages/piagent-webui/gateway/source-revert-store.ts +47 -0
- package/packages/piagent-webui/gateway/terminal-command-ledger.ts +33 -0
- package/packages/piagent-webui/gateway/terminal-mentions.ts +29 -0
- package/packages/piagent-webui/gateway/terminal-output-buffer.ts +58 -0
- package/packages/piagent-webui/gateway/terminal-router.ts +12 -0
- package/packages/piagent-webui/gateway/terminal-sessions.ts +247 -0
- package/packages/piagent-webui/gateway/workspace-write-sessions.ts +69 -0
- package/packages/piagent-webui/gateway/workspace-write-store.ts +6 -0
- package/packages/piagent-webui/package.json +14 -2
- package/packages/piagent-webui/server/checkpoint-command.ts +30 -0
- package/packages/piagent-webui/server/checkpoint-controller.ts +87 -0
- package/packages/piagent-webui/server/checkpoint-routes.ts +38 -0
- package/packages/piagent-webui/server/control-command-digest.ts +5 -0
- package/packages/piagent-webui/server/core-inspection-provider.ts +16 -22
- package/packages/piagent-webui/server/gateway-websocket.ts +36 -8
- package/packages/piagent-webui/server/loopback-server.ts +9 -0
- package/packages/piagent-webui/server/read-model-provider.ts +3 -0
- package/packages/piagent-webui/server/read-only-router.ts +3 -0
- package/packages/piagent-webui/server/session-auth.ts +4 -1
- package/packages/piagent-webui/server/session-source-revert-routes.ts +54 -0
- package/packages/piagent-webui/server/source-projection-binding.ts +18 -0
- package/packages/piagent-webui/server/source-revert-controller.ts +225 -0
- package/packages/piagent-webui/server/terminal-command.ts +35 -0
- package/packages/piagent-webui/server/terminal-websocket-stream.ts +56 -0
- package/packages/piagent-webui/server/transcript-projection.ts +2 -1
- package/packages/piagent-webui/server/workspace-read-routes.ts +32 -0
- package/packages/piagent-webui/server/workspace-reader.ts +23 -0
- package/packages/piagent-webui/server/workspace-write-controller.ts +118 -0
- package/packages/piagent-webui/server/workspace-write-routes.ts +38 -0
- package/packages/piagent-webui/shared/terminal-message.ts +23 -0
- package/schemas/piagent-webui/catalog-v1.json +63 -0
- package/schemas/piagent-webui/checkpoint-v1.schema.json +466 -0
- package/schemas/piagent-webui/control-command-v1.schema.json +68 -3
- package/schemas/piagent-webui/diff-v1.schema.json +4 -0
- package/schemas/piagent-webui/gateway-protocol-v1.schema.json +123 -3
- package/schemas/piagent-webui/session-catalog-v1.schema.json +1 -1
- package/schemas/piagent-webui/session-command-v1.schema.json +1 -1
- package/schemas/piagent-webui/snapshot-v1.schema.json +2 -1
- package/schemas/piagent-webui/source-revert-v1.schema.json +22 -3
- package/schemas/piagent-webui/terminal-v1.schema.json +495 -0
- package/schemas/piagent-webui/workspace-file-v1.schema.json +79 -0
- package/schemas/piagent-webui/workspace-paths-v1.schema.json +71 -0
- package/schemas/piagent-webui/workspace-search-v1.schema.json +80 -0
- package/schemas/piagent-webui/workspace-tree-v1.schema.json +87 -0
- package/schemas/piagent-webui/workspace-write-v1.schema.json +276 -0
- package/schemas/project-profile.schema.json +8 -3
- package/scripts/company-terminal.mjs +16 -11
- package/scripts/pi-auto.sh +5 -1
- package/scripts/team-doctor.sh +8 -0
- package/packages/piagent-webui/dist/client/assets/MarkdownMessage-CfgyQQbW.js +0 -29
- package/packages/piagent-webui/dist/client/assets/index-HyzWKvDu.js +0 -234
- package/packages/piagent-webui/dist/client/assets/index-_0nGP2n3.css +0 -1
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { reviewDigest } from "../inspection/review-state-contract.ts";
|
|
3
|
+
import { sessionMutationObserver } from "../inspection/session-mutation-observer.ts";
|
|
4
|
+
import { sessionAuthoredHunkRefs } from "../inspection/session-hunk-provenance.ts";
|
|
5
|
+
import { inspectWorkspaceFile, workspacePathFlags } from "../../extensions/workspace-inspection.ts";
|
|
1
6
|
import { randomBytes } from "node:crypto";
|
|
2
7
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
3
8
|
|
|
@@ -15,7 +20,8 @@ export type SourceMutationGuardBindings = {
|
|
|
15
20
|
};
|
|
16
21
|
|
|
17
22
|
export function createSourceMutationGuardBindings(policy: BasePolicy,
|
|
18
|
-
loadProfile: (ctx: ExtensionContext) => ProjectProfile
|
|
23
|
+
loadProfile: (ctx: ExtensionContext) => ProjectProfile,
|
|
24
|
+
writable?: (ctx: ExtensionContext, profile: ProjectProfile) => boolean): SourceMutationGuardBindings {
|
|
19
25
|
const guardInstanceId = `guard.${randomBytes(32).toString("hex")}`, bindings = new Map<string, () => void>();
|
|
20
26
|
const key = (ctx: ExtensionContext) => `${ctx.cwd}\0${ctx.sessionManager.getSessionId()}`;
|
|
21
27
|
return {
|
|
@@ -24,7 +30,26 @@ export function createSourceMutationGuardBindings(policy: BasePolicy,
|
|
|
24
30
|
bindings.set(bindingKey, piSourceMutationGuard.bind({ cwd: ctx.cwd, rawSessionId: ctx.sessionManager.getSessionId(), guardInstanceId,
|
|
25
31
|
facts: () => {
|
|
26
32
|
const task = activeSessionTask(ctx.cwd, ctx.sessionManager.getSessionId()) as TaskContract | undefined;
|
|
27
|
-
if (!task)
|
|
33
|
+
if (!task) {
|
|
34
|
+
const profile = loadProfile(ctx), canWrite = writable?.(ctx, profile) === true;
|
|
35
|
+
const workspacePolicy = { policy: policy as unknown as Record<string, unknown>, profile: profile as unknown as Record<string, unknown>, readOnly: !canWrite };
|
|
36
|
+
const paths = effectiveProtectedPaths(policy, profile);
|
|
37
|
+
return { taskId: null, taskRunId: null, taskRevision: null, taskState: "none" as const, sessionBound: true, writable: canWrite,
|
|
38
|
+
controlRevision: reviewDigest({ guardInstanceId, sessionId: ctx.sessionManager.getSessionId(), canWrite, paths }), idle: ctx.isIdle(),
|
|
39
|
+
isProtectedPath: (file: string) => { const flags = workspacePathFlags(file, workspacePolicy); return flags.protected || flags.readOnly; },
|
|
40
|
+
sessionObservation: file => sessionMutationObserver.current(ctx.cwd, ctx.sessionManager.getSessionId(), file, workspacePolicy),
|
|
41
|
+
sessionReverted: (authority, before, committed) => {
|
|
42
|
+
const relative = path.relative(ctx.cwd, path.resolve(authority.repoRoot, authority.repoPath)).split(path.sep).join("/");
|
|
43
|
+
sessionMutationObserver.reverted(ctx.cwd, ctx.sessionManager.getSessionId(), relative, before, committed, workspacePolicy);
|
|
44
|
+
},
|
|
45
|
+
sessionHunkRefs: authority => {
|
|
46
|
+
const relative = path.relative(ctx.cwd, path.resolve(authority.repoRoot, authority.repoPath)).split(path.sep).join("/");
|
|
47
|
+
const observation = sessionMutationObserver.current(ctx.cwd, ctx.sessionManager.getSessionId(), relative, workspacePolicy);
|
|
48
|
+
if (!observation) return [];
|
|
49
|
+
const current = inspectWorkspaceFile(ctx.cwd, relative, workspacePolicy);
|
|
50
|
+
return current.content === null ? [] : sessionAuthoredHunkRefs(observation, current.content, authority.patchAuthority);
|
|
51
|
+
} };
|
|
52
|
+
}
|
|
28
53
|
const control = inspectTaskControlState(ctx.cwd, task);
|
|
29
54
|
const taskState = task.trace.outcome !== "pending" || control.state === "terminal" ? "terminal"
|
|
30
55
|
: control.state === "active" ? "active" : "unknown";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SessionMutationObservation } from "../inspection/session-mutation-observer.ts";
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
|
|
@@ -19,11 +20,16 @@ const DIGEST = /^sha256:[a-f0-9]{64}$/;
|
|
|
19
20
|
const WORKSPACE = /^wt-content-v2:[a-f0-9]{64}$/;
|
|
20
21
|
|
|
21
22
|
export type SourceMutationGuardFacts = {
|
|
22
|
-
taskId: string;
|
|
23
|
-
taskRunId: string;
|
|
24
|
-
taskRevision: string;
|
|
23
|
+
taskId: string | null;
|
|
24
|
+
taskRunId: string | null;
|
|
25
|
+
taskRevision: string | null;
|
|
25
26
|
controlRevision: string;
|
|
26
|
-
taskState: "active" | "terminal" | "unknown";
|
|
27
|
+
taskState: "active" | "terminal" | "unknown" | "none";
|
|
28
|
+
sessionBound?: boolean;
|
|
29
|
+
writable?: boolean;
|
|
30
|
+
sessionObservation?(path: string): SessionMutationObservation | null;
|
|
31
|
+
sessionReverted?(authority: SourceRevertAuthority, beforeDigest: string, committedDigest: string): void;
|
|
32
|
+
sessionHunkRefs?(authority: SourceRevertAuthority): string[];
|
|
27
33
|
idle: boolean;
|
|
28
34
|
isProtectedPath(projectRelativePath: string): boolean;
|
|
29
35
|
};
|
|
@@ -42,8 +48,8 @@ export type SourceMutationGuardRequest = {
|
|
|
42
48
|
};
|
|
43
49
|
export type SourceRevertGuardRequest = {
|
|
44
50
|
cwd: string; rawSessionId: string;
|
|
45
|
-
identity: { projectRef: string; runtimeInstanceId: string; sessionRef: string; taskId: string; taskRunId: string };
|
|
46
|
-
action: "source.revert"; expectedTaskRevision: string; expectedControlRevision: string; expectedIndexPreimage: string;
|
|
51
|
+
identity: { projectRef: string; runtimeInstanceId: string; sessionRef: string; taskId: string | null; taskRunId: string | null };
|
|
52
|
+
action: "source.revert"; expectedTaskRevision: string | null; expectedControlRevision: string; expectedIndexPreimage: string;
|
|
47
53
|
expectedWorkspacePreimage: string; previewRef: string; confirmedPreviewDigest: string; authority: SourceRevertAuthority;
|
|
48
54
|
};
|
|
49
55
|
|
|
@@ -84,10 +90,22 @@ export class PiSourceMutationGuard {
|
|
|
84
90
|
available(cwd: string, rawSessionId: string): boolean {
|
|
85
91
|
try {
|
|
86
92
|
const binding = this.#bindings.get(bindingKey(cwd, rawSessionId)), facts = binding?.facts();
|
|
87
|
-
return Boolean(facts && facts.taskState === "active" && facts.idle);
|
|
93
|
+
return Boolean(facts && (facts.taskState === "active" || facts.sessionBound === true && facts.taskState === "none" && facts.writable === true) && facts.idle);
|
|
88
94
|
} catch { return false; }
|
|
89
95
|
}
|
|
90
96
|
|
|
97
|
+
sessionObservation(cwd: string, rawSessionId: string, file: string): SessionMutationObservation | null {
|
|
98
|
+
try { const facts = this.#bindings.get(bindingKey(cwd, rawSessionId))?.facts();
|
|
99
|
+
return facts?.sessionBound === true ? facts.sessionObservation?.(file) ?? null : null;
|
|
100
|
+
} catch { return null; }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
sessionControlRevision(cwd: string, rawSessionId: string): string | null {
|
|
104
|
+
try { const facts = this.#bindings.get(bindingKey(cwd, rawSessionId))?.facts();
|
|
105
|
+
return facts?.sessionBound === true && facts.taskState === "none" ? facts.controlRevision : null;
|
|
106
|
+
} catch { return null; }
|
|
107
|
+
}
|
|
108
|
+
|
|
91
109
|
async execute(request: SourceMutationGuardRequest): Promise<SourceIndexTransactionResult> {
|
|
92
110
|
let binding: Binding | undefined;
|
|
93
111
|
try { binding = this.#bindings.get(bindingKey(request.cwd, request.rawSessionId)); }
|
|
@@ -96,7 +114,7 @@ export class PiSourceMutationGuard {
|
|
|
96
114
|
const recheck = (): boolean => {
|
|
97
115
|
try {
|
|
98
116
|
const facts = binding!.facts();
|
|
99
|
-
return Boolean(facts && facts.taskState === "active" && facts.idle
|
|
117
|
+
return Boolean(this.#bindings.get(bindingKey(request.cwd, request.rawSessionId)) === binding && facts && facts.taskState === "active" && facts.idle
|
|
100
118
|
&& facts.taskId === request.identity.taskId && facts.taskRunId === request.identity.taskRunId
|
|
101
119
|
&& facts.taskRevision === request.expectedTaskRevision && facts.controlRevision === request.expectedControlRevision
|
|
102
120
|
&& this.#pathsAllowed(binding!, facts, request.authority));
|
|
@@ -116,15 +134,26 @@ export class PiSourceMutationGuard {
|
|
|
116
134
|
const recheck = (): boolean => {
|
|
117
135
|
try {
|
|
118
136
|
const facts = binding!.facts(), target = request.authority.target;
|
|
119
|
-
|
|
137
|
+
const sessionBound = request.identity.taskId === null && request.identity.taskRunId === null && request.expectedTaskRevision === null;
|
|
138
|
+
const active = sessionBound ? facts?.sessionBound === true && facts.taskState === "none" && facts.writable === true : facts?.taskState === "active";
|
|
139
|
+
const pathsAllowed = facts && this.#pathsAllowed(binding!, facts, { repoRoot: request.authority.repoRoot, repoPaths: [request.authority.repoPath] });
|
|
140
|
+
const authored = sessionBound && pathsAllowed ? facts?.sessionHunkRefs?.(request.authority) ?? [] : [];
|
|
141
|
+
const selected = target.hunkRefs.length ? target.hunkRefs : request.authority.patchAuthority.hunks.map(hunk => hunk.hunkRef);
|
|
142
|
+
return Boolean(this.#bindings.get(bindingKey(request.cwd, request.rawSessionId)) === binding && facts && active && pathsAllowed
|
|
143
|
+
&& (!sessionBound || selected.length > 0 && selected.every(ref => authored.includes(ref))) && facts.idle && Date.now() <= Date.parse(target.expiresAt)
|
|
120
144
|
&& facts.taskId === request.identity.taskId && facts.taskRunId === request.identity.taskRunId
|
|
121
145
|
&& facts.taskRevision === request.expectedTaskRevision && facts.controlRevision === request.expectedControlRevision
|
|
122
146
|
&& this.#pathsAllowed(binding!, facts, { repoRoot: request.authority.repoRoot, repoPaths: [request.authority.repoPath] }));
|
|
123
147
|
} catch { return false; }
|
|
124
148
|
};
|
|
125
149
|
if (!recheck()) return revertRejected(request, "mutation-guard-precondition-stale");
|
|
150
|
+
const relative = path.relative(binding.cwd, path.resolve(request.authority.repoRoot, request.authority.repoPath)).split(path.sep).join("/");
|
|
151
|
+
const before = binding.facts()?.sessionObservation?.(relative);
|
|
126
152
|
return executeGuardedSourceWorktreeRevert({ authority: request.authority, expectedIndexPreimage: request.expectedIndexPreimage,
|
|
127
|
-
expectedWorkspacePreimage: request.expectedWorkspacePreimage, recheck
|
|
153
|
+
expectedWorkspacePreimage: request.expectedWorkspacePreimage, recheck, onCommitted: digest => {
|
|
154
|
+
try { if (before && this.#bindings.get(bindingKey(request.cwd, request.rawSessionId)) === binding)
|
|
155
|
+
binding.facts()?.sessionReverted?.(request.authority, before.currentDigest, digest); } catch { /* Lost observation only disables further review. */ }
|
|
156
|
+
} });
|
|
128
157
|
}
|
|
129
158
|
|
|
130
159
|
#validRequest(request: SourceMutationGuardRequest): boolean {
|
|
@@ -150,9 +179,10 @@ export class PiSourceMutationGuard {
|
|
|
150
179
|
#validRevertRequest(request: SourceRevertGuardRequest): boolean {
|
|
151
180
|
try { validateSourceRevertTarget(request.authority.target); } catch { return false; }
|
|
152
181
|
const target = request.authority.target;
|
|
182
|
+
const sessionBound = request.identity.taskId === null && request.identity.taskRunId === null && request.expectedTaskRevision === null;
|
|
153
183
|
return request.action === "source.revert" && REF.test(request.identity.projectRef) && REF.test(request.identity.runtimeInstanceId)
|
|
154
|
-
&& REF.test(request.identity.sessionRef) && REF.test(request.identity.taskId) && REF.test(request.identity.taskRunId)
|
|
155
|
-
&& REVISION.test(request.
|
|
184
|
+
&& REF.test(request.identity.sessionRef) && (sessionBound || REF.test(request.identity.taskId!) && REF.test(request.identity.taskRunId!) && REVISION.test(request.expectedTaskRevision!))
|
|
185
|
+
&& REVISION.test(request.expectedControlRevision)
|
|
156
186
|
&& DIGEST.test(request.expectedIndexPreimage) && WORKSPACE.test(request.expectedWorkspacePreimage)
|
|
157
187
|
&& REF.test(request.previewRef) && DIGEST.test(request.confirmedPreviewDigest)
|
|
158
188
|
&& request.previewRef === target.previewRef && request.confirmedPreviewDigest === target.confirmedPreviewDigest
|
|
@@ -40,7 +40,7 @@ async function gitDirectory(repoRoot: string): Promise<string> {
|
|
|
40
40
|
if (!path.isAbsolute(candidate) || !stat.isDirectory() || stat.isSymbolicLink()) throw new Error("git-directory-invalid");
|
|
41
41
|
return resolved;
|
|
42
42
|
}
|
|
43
|
-
async function restoreWholeFile(authority: SourceRevertAuthority, recheck: () => Promise<boolean>): Promise<
|
|
43
|
+
async function restoreWholeFile(authority: SourceRevertAuthority, recheck: () => Promise<boolean>): Promise<string> {
|
|
44
44
|
const bytes = await runReadOnlyGit(authority.repoRoot, ["cat-file", "blob", authority.indexObject], { maxBytes: 16 * 1024 * 1024 });
|
|
45
45
|
const target = path.resolve(authority.repoRoot, authority.repoPath), parent = fs.realpathSync.native(path.dirname(target));
|
|
46
46
|
if (parent !== path.dirname(target) || !target.startsWith(`${authority.repoRoot}${path.sep}`)) throw new Error("revert-target-unsafe");
|
|
@@ -52,8 +52,9 @@ async function restoreWholeFile(authority: SourceRevertAuthority, recheck: () =>
|
|
|
52
52
|
try { if (!await recheck()) throw new Error("revert-preimage-stale"); fs.renameSync(temporary, target); }
|
|
53
53
|
finally { fs.rmSync(temporary, { force: true }); }
|
|
54
54
|
const actual = fs.readFileSync(target); if (!actual.equals(bytes)) throw new Error("revert-postcondition-failed");
|
|
55
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
55
56
|
}
|
|
56
|
-
type PreparedSelectedHunk = { stagingPath: string; target: string; initialMode: number };
|
|
57
|
+
type PreparedSelectedHunk = { stagingPath: string; target: string; initialMode: number; contentDigest: string };
|
|
57
58
|
function inside(root: string, candidate: string): boolean {
|
|
58
59
|
const relative = path.relative(root, candidate);
|
|
59
60
|
return relative === "" || relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
|
|
@@ -101,7 +102,7 @@ async function prepareSelectedHunk(authority: SourceRevertAuthority, hunkRef: st
|
|
|
101
102
|
fs.fchmodSync(stagingDescriptor, result.mode & 0o777);
|
|
102
103
|
fs.fsyncSync(stagingDescriptor);
|
|
103
104
|
} finally { fs.closeSync(stagingDescriptor); }
|
|
104
|
-
return { stagingPath, target, initialMode: current.mode & 0o777 };
|
|
105
|
+
return { stagingPath, target, initialMode: current.mode & 0o777, contentDigest: createHash("sha256").update(candidate).digest("hex") };
|
|
105
106
|
} catch (error) {
|
|
106
107
|
cleanupStagingFile(stagingPath);
|
|
107
108
|
throw error;
|
|
@@ -109,8 +110,11 @@ async function prepareSelectedHunk(authority: SourceRevertAuthority, hunkRef: st
|
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
export async function executeGuardedSourceWorktreeRevert(options: { authority: SourceRevertAuthority; expectedIndexPreimage: string;
|
|
112
|
-
expectedWorkspacePreimage: string; recheck(): boolean; timeoutMs?: number }): Promise<SourceIndexTransactionResult> {
|
|
113
|
+
expectedWorkspacePreimage: string; recheck(): boolean; onCommitted?(contentDigest: string): void; timeoutMs?: number }): Promise<SourceIndexTransactionResult> {
|
|
113
114
|
const before = { beforeIndexPreimage: options.expectedIndexPreimage, beforeWorkspacePreimage: options.expectedWorkspacePreimage };
|
|
115
|
+
const observeCommitted = (digest: string) => {
|
|
116
|
+
try { options.onCommitted?.(digest); } catch { /* Observation failure must not change the file transaction outcome. */ }
|
|
117
|
+
};
|
|
114
118
|
let lockPath = "", ownsLock = false, committed = false;
|
|
115
119
|
try {
|
|
116
120
|
const gitDir = await gitDirectory(options.authority.repoRoot), lockName = createHash("sha256").update(options.authority.repoPath).digest("hex");
|
|
@@ -141,8 +145,9 @@ export async function executeGuardedSourceWorktreeRevert(options: { authority: S
|
|
|
141
145
|
return result({ state: "rejected", reasonCode: "mutation-preimage-stale", ...before,
|
|
142
146
|
afterIndexPreimage: null, afterWorkspacePreimage: null });
|
|
143
147
|
fs.renameSync(prepared.stagingPath, prepared.target);
|
|
148
|
+
observeCommitted(prepared.contentDigest);
|
|
144
149
|
} finally { cleanupStagingFile(prepared.stagingPath); }
|
|
145
|
-
} else await restoreWholeFile(options.authority, finalRecheck);
|
|
150
|
+
} else { const digest = await restoreWholeFile(options.authority, finalRecheck); observeCommitted(digest); }
|
|
146
151
|
committed = true;
|
|
147
152
|
const afterIndexPreimage = await collectIndexPreimage(options.authority.repoRoot);
|
|
148
153
|
const afterWorkspacePreimage = collectSelectedWorkspacePreimage(options.authority.repoRoot, [options.authority.repoPath]);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import type { BasePolicy, ProjectProfile } from "../../extensions/guard-types.js";
|
|
5
|
+
import type { WorkspacePolicy } from "../../extensions/workspace-inspection.ts";
|
|
6
|
+
import { WorkspaceWriteError, writeWorkspaceFile, type WorkspaceWriteInput } from "../../extensions/workspace-write.ts";
|
|
7
|
+
|
|
8
|
+
type Binding = { owner: string; policy(): WorkspacePolicy };
|
|
9
|
+
const key = (cwd: string, sessionId: string) => `${fs.realpathSync(cwd)}\0${sessionId}`;
|
|
10
|
+
|
|
11
|
+
// Gateway writes use the live guard's permission resolver, including its
|
|
12
|
+
// environment/session overrides. A persisted UI message is not authority.
|
|
13
|
+
export class WorkspaceWriteAuthority {
|
|
14
|
+
readonly #bindings = new Map<string, Binding>();
|
|
15
|
+
bind(cwd: string, sessionId: string, binding: Binding): () => void {
|
|
16
|
+
const identity = key(cwd, sessionId); this.#bindings.set(identity, binding);
|
|
17
|
+
return () => { if (this.#bindings.get(identity)?.owner === binding.owner) this.#bindings.delete(identity); };
|
|
18
|
+
}
|
|
19
|
+
writable(cwd: string, sessionId: string): boolean {
|
|
20
|
+
try { const policy = this.#bindings.get(key(cwd, sessionId))?.policy(); return !!policy && !policy.readOnly; }
|
|
21
|
+
catch { return false; }
|
|
22
|
+
}
|
|
23
|
+
write(cwd: string, sessionId: string, input: WorkspaceWriteInput) {
|
|
24
|
+
const policy = this.#bindings.get(key(cwd, sessionId))?.policy();
|
|
25
|
+
if (!policy || policy.readOnly) throw new WorkspaceWriteError("read-only");
|
|
26
|
+
return writeWorkspaceFile(cwd, input, policy);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Pi loads extensions through its TS loader, while Gateway uses native ESM.
|
|
30
|
+
// Share the live binding across those module instances, as source mutation does.
|
|
31
|
+
const AUTHORITY_KEY = Symbol.for("piagent.webui.workspace-write-authority.v1");
|
|
32
|
+
const root = globalThis as typeof globalThis & { [AUTHORITY_KEY]?: WorkspaceWriteAuthority };
|
|
33
|
+
export const workspaceWriteAuthority = root[AUTHORITY_KEY] ??= new WorkspaceWriteAuthority();
|
|
34
|
+
|
|
35
|
+
export function createWorkspaceWriteAuthorityBindings(policy: BasePolicy, loadProfile: (ctx: ExtensionContext) => ProjectProfile,
|
|
36
|
+
writable: (ctx: ExtensionContext, profile: ProjectProfile) => boolean) {
|
|
37
|
+
const owner = randomUUID(), bindings = new Map<string, () => void>();
|
|
38
|
+
return {
|
|
39
|
+
bind(ctx: ExtensionContext) {
|
|
40
|
+
const sessionId = ctx.sessionManager.getSessionId(), identity = key(ctx.cwd, sessionId);
|
|
41
|
+
bindings.get(identity)?.();
|
|
42
|
+
bindings.set(identity, workspaceWriteAuthority.bind(ctx.cwd, sessionId, { owner, policy: () => {
|
|
43
|
+
const profile = loadProfile(ctx);
|
|
44
|
+
return { policy: policy as unknown as Record<string, unknown>, profile: profile as unknown as Record<string, unknown>, readOnly: !writable(ctx, profile) };
|
|
45
|
+
} }));
|
|
46
|
+
},
|
|
47
|
+
unbind(ctx: ExtensionContext) {
|
|
48
|
+
const identity = key(ctx.cwd, ctx.sessionManager.getSessionId()); bindings.get(identity)?.(); bindings.delete(identity);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
|
|
4
|
+
// Whether the process that wrote a lock or a capture at `since` (ms) still
|
|
5
|
+
// holds it. A live process number alone is not enough: after a reboot, or
|
|
6
|
+
// once the number is reused, an unrelated process would hold the lock forever.
|
|
7
|
+
// So the owner must have started before the record and after the last boot.
|
|
8
|
+
export function ownerAlive(pid, since, { now = Date.now(), uptime = os.uptime(), started = processStart } = {}) {
|
|
9
|
+
try { process.kill(pid, 0); } catch (error) { if (error.code === 'ESRCH') return false; throw error; }
|
|
10
|
+
if (since < now - uptime * 1000) return false;
|
|
11
|
+
const start = started(pid);
|
|
12
|
+
return start === null || start <= since + 1000;
|
|
13
|
+
}
|
|
14
|
+
function processStart(pid) {
|
|
15
|
+
try {
|
|
16
|
+
const text = execFileSync('/bin/ps', ['-o', 'lstart=', '-p', String(pid)], { encoding: 'utf8', timeout: 2000, env: { ...process.env, LC_ALL: 'C' } }).trim();
|
|
17
|
+
const value = Date.parse(text);
|
|
18
|
+
return Number.isFinite(value) ? value : null;
|
|
19
|
+
} catch { return null; }
|
|
20
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
|
|
3
|
+
const INTERVAL = 2000;
|
|
4
|
+
function table() {
|
|
5
|
+
try {
|
|
6
|
+
return execFileSync('/bin/ps', ['-axo', 'pid=,ppid='], { encoding: 'utf8', timeout: 2000, maxBuffer: 4 * 1024 * 1024 })
|
|
7
|
+
.trim().split('\n').map(line => line.trim().split(/\s+/).map(Number));
|
|
8
|
+
} catch { return []; }
|
|
9
|
+
}
|
|
10
|
+
const tree = (rows, root) => {
|
|
11
|
+
const found = new Set(), queue = [root];
|
|
12
|
+
for (const parent of queue) for (const [pid, ppid] of rows) if (ppid === parent && pid > 1 && pid !== process.pid && !found.has(pid)) { found.add(pid); queue.push(pid); }
|
|
13
|
+
return found;
|
|
14
|
+
};
|
|
15
|
+
const signal = (pid, name) => { try { process.kill(pid, name); } catch { /* already gone */ } };
|
|
16
|
+
|
|
17
|
+
// A shell's background job (`sleep 300 &`, then `exit`) leaves the shell's
|
|
18
|
+
// process group, and once the shell ends it is re-parented to init and no
|
|
19
|
+
// longer in its tree. The tree is therefore watched while the shell runs, so
|
|
20
|
+
// such jobs stop with their terminal. A watched process is signalled only
|
|
21
|
+
// while it is still orphaned (parent 1) or still under the root, never after
|
|
22
|
+
// its number was reused by an unrelated process.
|
|
23
|
+
export class ProcessTreeWatch {
|
|
24
|
+
#roots = new Map();
|
|
25
|
+
#timer = null;
|
|
26
|
+
watch(root) {
|
|
27
|
+
this.#roots.set(root, new Set());
|
|
28
|
+
this.#timer ??= setInterval(() => this.#scan(), INTERVAL);
|
|
29
|
+
this.#timer.unref?.();
|
|
30
|
+
}
|
|
31
|
+
#scan(rows = table()) {
|
|
32
|
+
for (const [root, seen] of this.#roots) for (const pid of tree(rows, root)) if (seen.size < 4096) seen.add(pid);
|
|
33
|
+
return rows;
|
|
34
|
+
}
|
|
35
|
+
async stop(root) {
|
|
36
|
+
const seen = this.#roots.get(root); if (!seen) return;
|
|
37
|
+
const rows = this.#scan(), current = tree(rows, root), parents = new Map(rows.map(([pid, ppid]) => [pid, ppid]));
|
|
38
|
+
this.#roots.delete(root);
|
|
39
|
+
if (!this.#roots.size) { clearInterval(this.#timer); this.#timer = null; }
|
|
40
|
+
const targets = [...seen].filter(pid => current.has(pid) || parents.get(pid) === 1);
|
|
41
|
+
for (const pid of targets) signal(pid, 'SIGTERM');
|
|
42
|
+
if (!targets.length) return;
|
|
43
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
44
|
+
for (const pid of targets) signal(pid, 'SIGKILL');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -2,6 +2,8 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
|
|
5
|
+
export type MutationProofReader = (cwd: string, file: string) => { content: string; digest: string } | undefined;
|
|
6
|
+
|
|
5
7
|
const MAX_PROOF_FILE_BYTES = 4 * 1024 * 1024;
|
|
6
8
|
|
|
7
9
|
export type ModelMutationProof = {
|
|
@@ -106,7 +108,7 @@ function patchStrings(input: Record<string, unknown>): string[] {
|
|
|
106
108
|
return Object.values(input).filter((value): value is string => typeof value === "string" && value.includes("*** "));
|
|
107
109
|
}
|
|
108
110
|
|
|
109
|
-
function patchProof(cwd: string, input: Record<string, unknown>, targets: string[], proof: ModelMutationProof): void {
|
|
111
|
+
function patchProof(cwd: string, input: Record<string, unknown>, targets: string[], proof: ModelMutationProof, read: MutationProofReader): void {
|
|
110
112
|
for (const patch of patchStrings(input)) {
|
|
111
113
|
const lines = patch.replace(/\r\n/g, "\n").split("\n");
|
|
112
114
|
for (let index = 0; index < lines.length; index += 1) {
|
|
@@ -127,7 +129,7 @@ function patchProof(cwd: string, input: Record<string, unknown>, targets: string
|
|
|
127
129
|
continue;
|
|
128
130
|
}
|
|
129
131
|
proof.replacePaths.push(file);
|
|
130
|
-
const before =
|
|
132
|
+
const before = read(cwd, file);
|
|
131
133
|
if (!before) continue;
|
|
132
134
|
proof.preContentDigests[file] = before.digest;
|
|
133
135
|
const projected = applyPatchHunks(before.content, section);
|
|
@@ -140,7 +142,8 @@ export function expectedModelMutationProof(
|
|
|
140
142
|
cwd: string,
|
|
141
143
|
toolName: string,
|
|
142
144
|
input: Record<string, unknown>,
|
|
143
|
-
targetPaths: string[]
|
|
145
|
+
targetPaths: string[],
|
|
146
|
+
read: MutationProofReader = stableFile
|
|
144
147
|
): ModelMutationProof {
|
|
145
148
|
const targets = [...new Set(targetPaths)];
|
|
146
149
|
const proof: ModelMutationProof = { expectedContentDigests: {}, preContentDigests: {}, fullContentPaths: [], replacePaths: [] };
|
|
@@ -153,13 +156,13 @@ export function expectedModelMutationProof(
|
|
|
153
156
|
rememberFullContent(targets[0], [input.content]);
|
|
154
157
|
} else if (toolName === "edit" && targets.length === 1) {
|
|
155
158
|
proof.replacePaths.push(targets[0]);
|
|
156
|
-
const before =
|
|
159
|
+
const before = read(cwd, targets[0]);
|
|
157
160
|
const edits = inputEdits(input);
|
|
158
161
|
if (before) proof.preContentDigests[targets[0]] = before.digest;
|
|
159
162
|
const projected = before && edits ? applyUniqueReplacements(before.content, edits) : undefined;
|
|
160
163
|
if (projected !== undefined) proof.expectedContentDigests[targets[0]] = [contentDigest(projected)];
|
|
161
164
|
} else if (toolName === "apply_patch") {
|
|
162
|
-
patchProof(cwd, input, targets, proof);
|
|
165
|
+
patchProof(cwd, input, targets, proof, read);
|
|
163
166
|
}
|
|
164
167
|
proof.fullContentPaths = [...new Set(proof.fullContentPaths)].sort();
|
|
165
168
|
proof.replacePaths = [...new Set(proof.replacePaths)].sort();
|
|
@@ -49,7 +49,7 @@ export function registerPermissionCommands(pi: ExtensionAPI, deps: Record<string
|
|
|
49
49
|
function emitCurrentPermissionStatus(ctx: ExtensionContext): void {
|
|
50
50
|
const profile = loadProfileFromContext(ctx);
|
|
51
51
|
const permissionProfile = resolvePermissionProfile(profile, policy, permissionOverrideFromContext(ctx));
|
|
52
|
-
ctx.ui.notify(`Piagent permission profile: ${permissionProfile.mode}`,
|
|
52
|
+
ctx.ui.notify(`Piagent permission profile: ${permissionProfile.mode}`, ["trusted-full-access", "bypass"].includes(permissionProfile.mode) ? "warning" : "info");
|
|
53
53
|
emitPermissionStatus(ctx, permissionProfile);
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -58,7 +58,7 @@ export function registerPermissionCommands(pi: ExtensionAPI, deps: Record<string
|
|
|
58
58
|
const profile = loadProfileFromContext(ctx);
|
|
59
59
|
const permissionProfile = resolvePermissionProfile(profile, policy, permissionOverrideFromContext(ctx));
|
|
60
60
|
const isActive = permissionProfile.mode === mode && !permissionProfile.warning;
|
|
61
|
-
const level = !isActive || mode === "trusted-full-access" ? "warning" : "info";
|
|
61
|
+
const level = !isActive || mode === "trusted-full-access" || mode === "bypass" ? "warning" : "info";
|
|
62
62
|
const message = isActive
|
|
63
63
|
? `Piagent permission profile set to ${mode} for this session.`
|
|
64
64
|
: `Requested ${mode}, but active profile is ${permissionProfile.mode}.`;
|
|
@@ -67,6 +67,9 @@ export function registerPermissionCommands(pi: ExtensionAPI, deps: Record<string
|
|
|
67
67
|
if (permissionProfile.mode === "trusted-full-access") {
|
|
68
68
|
ctx.ui.notify("Trusted full access is active; protected paths, secret redaction, and destructive/external confirmations remain enforced.", "warning");
|
|
69
69
|
}
|
|
70
|
+
if (permissionProfile.mode === "bypass") {
|
|
71
|
+
ctx.ui.notify("Bypass is active: nothing is asked or blocked in this personal session (deletes, pushes, protected paths included). Output redaction and /undo checkpoints remain. Company sessions keep their own rules.", "warning");
|
|
72
|
+
}
|
|
70
73
|
emitPermissionStatus(ctx, permissionProfile);
|
|
71
74
|
if (request.trim()) sendWorkflowFollowUp(request.trim());
|
|
72
75
|
}
|
|
@@ -75,6 +78,7 @@ export function registerPermissionCommands(pi: ExtensionAPI, deps: Record<string
|
|
|
75
78
|
if (["read", "readonly", "read-only", "ro"].includes(action)) return "read-only";
|
|
76
79
|
if (["write", "workspace", "workspace-write", "ww"].includes(action)) return "workspace-write";
|
|
77
80
|
if (["full", "full-access", "trusted", "trusted-full-access"].includes(action)) return "trusted-full-access";
|
|
81
|
+
if (["bypass", "yolo", "dangerously-bypass"].includes(action)) return "bypass";
|
|
78
82
|
return undefined;
|
|
79
83
|
}
|
|
80
84
|
|
|
@@ -86,6 +90,7 @@ export function registerPermissionCommands(pi: ExtensionAPI, deps: Record<string
|
|
|
86
90
|
{ value: "read-only", label: "Read-only", description: "Scout/review without writes" },
|
|
87
91
|
{ value: "workspace-write", label: "Workspace write", description: "Normal governed implementation mode" },
|
|
88
92
|
{ value: "full-access", label: "Full access", description: "Trusted local full access; guardrails still apply" },
|
|
93
|
+
{ value: "bypass", label: "Bypass", description: "Nothing asked or blocked (personal sessions only); redaction and /undo remain" },
|
|
89
94
|
{ value: "help", label: "Help", description: "Show typed forms" }
|
|
90
95
|
], "status");
|
|
91
96
|
if (chosen && chosen !== "help") {
|
|
@@ -99,6 +104,7 @@ export function registerPermissionCommands(pi: ExtensionAPI, deps: Record<string
|
|
|
99
104
|
"read: /permission read-only",
|
|
100
105
|
"write: /permission workspace-write",
|
|
101
106
|
"full: /permission full-access",
|
|
107
|
+
"bypass: /permission bypass (personal; nothing asked or blocked)",
|
|
102
108
|
"legacy: /piagent-permission"
|
|
103
109
|
].join("\n"));
|
|
104
110
|
return;
|
|
@@ -114,6 +120,7 @@ export function registerPermissionCommands(pi: ExtensionAPI, deps: Record<string
|
|
|
114
120
|
"read: /permission read-only",
|
|
115
121
|
"write: /permission workspace-write",
|
|
116
122
|
"full: /permission full-access",
|
|
123
|
+
"bypass: /permission bypass (personal; nothing asked or blocked)",
|
|
117
124
|
"legacy: /piagent-permission"
|
|
118
125
|
].join("\n"));
|
|
119
126
|
return;
|
|
@@ -174,5 +181,6 @@ export function registerPermissionCommands(pi: ExtensionAPI, deps: Record<string
|
|
|
174
181
|
registerPermissionProfileCommand("workspace-write", "workspace-write", "Switch this session to workspace-write permission profile");
|
|
175
182
|
registerPermissionProfileCommand("full-access", "trusted-full-access", "Switch this session to trusted full-access permission profile");
|
|
176
183
|
registerPermissionProfileCommand("trusted-full-access", "trusted-full-access", "Alias for /full-access");
|
|
184
|
+
registerPermissionProfileCommand("bypass", "bypass", "Switch this personal session to bypass: nothing asked or blocked");
|
|
177
185
|
|
|
178
186
|
}
|
|
@@ -208,7 +208,7 @@ export function registerTaskEvidenceTools(pi: ExtensionAPI, deps: Record<string,
|
|
|
208
208
|
if (
|
|
209
209
|
projectRelative
|
|
210
210
|
&& capabilityState.filesystemRead
|
|
211
|
-
&&
|
|
211
|
+
&& !["trusted-full-access", "bypass"].includes(permissionProfile.mode)
|
|
212
212
|
&& !matchesAnyPath(projectRelative, capabilityState.filesystemRead)
|
|
213
213
|
) {
|
|
214
214
|
return {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
export const WORKSPACE_WRITE_ENTRY: "piagent-workspace-write";
|
|
3
|
+
export function takeWorkspaceMemberEditNotice(manager: { getBranch(): any[] }): {
|
|
4
|
+
customType: string; display: boolean; content: string; details: { throughEntryId: string };
|
|
5
|
+
} | null;
|
|
6
|
+
export function workspaceMemberEditsSince(manager: { getEntries?(): any[] } | null | undefined, since: number): Set<string>;
|
|
7
|
+
export function registerWorkspaceMemberEdits(pi: ExtensionAPI): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export const WORKSPACE_WRITE_ENTRY = 'piagent-workspace-write';
|
|
2
|
+
const NOTICE = 'piagent-member-edited';
|
|
3
|
+
|
|
4
|
+
// Receipts contain paths/digests, never the member's file contents. Read the
|
|
5
|
+
// current branch so a fork or rewind cannot deliver notes from another branch.
|
|
6
|
+
export function takeWorkspaceMemberEditNotice(manager) {
|
|
7
|
+
const entries = manager.getBranch();
|
|
8
|
+
let start = 0;
|
|
9
|
+
for (let index = entries.length - 1; index >= 0; index--) {
|
|
10
|
+
if (entries[index].type !== 'custom_message' || entries[index].customType !== NOTICE) continue;
|
|
11
|
+
const through = entries.findIndex(entry => entry.id === entries[index].details?.throughEntryId);
|
|
12
|
+
if (through >= 0 && through < index) { start = through + 1; break; }
|
|
13
|
+
}
|
|
14
|
+
const edits = entries.slice(start).filter(entry => entry.type === 'custom' && entry.customType === WORKSPACE_WRITE_ENTRY
|
|
15
|
+
&& entry.data?.phase === 'settled' && entry.data?.resultCode === 'saved');
|
|
16
|
+
const paths = [...new Set(edits.map(entry => entry.data.path)
|
|
17
|
+
.filter(value => typeof value === 'string' && value.length <= 4096 && !/[\x00-\x1f\x7f]/.test(value)))];
|
|
18
|
+
if (!paths.length) return null;
|
|
19
|
+
// Delivery itself acknowledges the receipts. A failed send leaves them
|
|
20
|
+
// pending; receipts appended during delivery remain for the next turn.
|
|
21
|
+
return { customType: NOTICE, display: true, details: { throughEntryId: edits.at(-1).id },
|
|
22
|
+
content: `Member edited ${paths.slice(0, 16).map(value => JSON.stringify(value.slice(0, 256))).join(', ')}${paths.length > 16 ? ` and ${paths.length - 16} more files` : ''}. Read their current contents before editing; earlier reads may be stale.` };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Files the member saved from the workspace editor at or after `since` (ms).
|
|
26
|
+
// Checkpoints treat them as the member's, never as part of an agent turn.
|
|
27
|
+
export function workspaceMemberEditsSince(manager, since) {
|
|
28
|
+
const paths = new Set();
|
|
29
|
+
for (const entry of manager?.getEntries?.() ?? []) {
|
|
30
|
+
const data = entry.type === 'custom' && entry.customType === WORKSPACE_WRITE_ENTRY ? entry.data : null;
|
|
31
|
+
if (data?.phase === 'settled' && data.resultCode === 'saved' && typeof data.path === 'string' && Date.parse(data.settledAt) >= since) paths.add(data.path);
|
|
32
|
+
}
|
|
33
|
+
return paths;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function registerWorkspaceMemberEdits(pi) {
|
|
37
|
+
pi.on('before_agent_start', (_event, ctx) => {
|
|
38
|
+
const message = takeWorkspaceMemberEditNotice(ctx.sessionManager);
|
|
39
|
+
if (message) return { message };
|
|
40
|
+
});
|
|
41
|
+
}
|
|
@@ -45,7 +45,8 @@ function sameFile(left: fs.Stats, right: fs.Stats): boolean {
|
|
|
45
45
|
|
|
46
46
|
function openRegularFile(repoRoot: string, repoPath: string): { descriptor: number; stat: fs.Stats; candidate: SafeCandidate } {
|
|
47
47
|
const candidate = safeCandidate(repoRoot, repoPath);
|
|
48
|
-
|
|
48
|
+
// A non-regular entry (notably a FIFO) must reach the fstat refusal without blocking.
|
|
49
|
+
const descriptor = fs.openSync(candidate.absolute, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0) | (fs.constants.O_NONBLOCK ?? 0));
|
|
49
50
|
try {
|
|
50
51
|
const stat = fs.fstatSync(descriptor);
|
|
51
52
|
if (!stat.isFile()) throw new WorkspaceReadError("not-file", "Workspace entry is not a regular file");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{U as t,b as n,d as r,f as i,u as a}from"./useTheme-_ESOj7MI.js";import{A as o,C as s,D as c,E as l,N as u,S as d,T as f,_ as p,a as m,i as h,o as g,p as _,w as v}from"./ui-preferences-DiddStu0.js";import{r as y}from"./Typography-DMZL1kLS.js";var b=e(t(),1),x=n(),S=b.createContext();function C({value:e,...t}){return(0,x.jsx)(S.Provider,{value:e??!0,...t})}var w=()=>b.useContext(S)??!1;function T(e){return typeof e==`string`}function E(e,t=166){let n;function r(...r){clearTimeout(n),n=setTimeout(()=>{e.apply(this,r)},t)}return r.clear=()=>{clearTimeout(n)},r}function D(e){return e&&e.ownerDocument||document}function O(e){return D(e).defaultView||window}var k=u,A=D;function j(e){let t=e.activeElement;for(;t?.shadowRoot?.activeElement!=null;)t=t.shadowRoot.activeElement;return t}var ee=j;function M(e,t,n){return e===void 0||T(e)?t:{...t,ownerState:{...t.ownerState,...n}}}function N(e,t,n){return typeof e==`function`?e(t,n):e}function P(e,t){let n=e.charCodeAt(2);return e[0]===`o`&&e[1]===`n`&&n>=65&&n<=90&&typeof t==`function`}function F(e){if(e===void 0)return{};let t={};for(let n of Object.keys(e))P(n,e[n])&&(t[n]=e[n]);return t}function I(e){if(e===void 0)return{};let t={};return Object.keys(e).filter(t=>!(t.match(/^on[A-Z]/)&&typeof e[t]==`function`)).forEach(n=>{t[n]=e[n]}),t}function te(e){let{getSlotProps:t,additionalProps:n,externalSlotProps:r,externalForwardedProps:a,className:o}=e;if(!t){let e=i(n?.className,o,a?.className,r?.className),t={...n?.style,...a?.style,...r?.style},s={...n,...a,...r};return e.length>0&&(s.className=e),Object.keys(t).length>0&&(s.style=t),{props:s,internalRef:void 0}}let s=F({...a,...r}),c=I(r),l=I(a),u=t(s),d=i(u?.className,n?.className,o,a?.className,r?.className),f={...u?.style,...n?.style,...a?.style,...r?.style},p={...u,...n,...l,...c};return d.length>0&&(p.className=d),Object.keys(f).length>0&&(p.style=f),{props:p,internalRef:u.ref}}function L(e,t){let{className:n,elementType:r,ownerState:i,externalForwardedProps:a,internalForwardedProps:o,shouldForwardComponentProp:s=!1,...c}=t,{component:l,slots:u={[e]:void 0},slotProps:d={[e]:void 0},...p}=a,m=u[e]||r,h=N(d[e],i),{props:{component:g,..._},internalRef:v}=te({className:n,...c,externalForwardedProps:e===`root`?p:void 0,externalSlotProps:h}),y=f(v,h?.ref,t.ref),b=e===`root`?g||l:g;return[m,M(m,{...e===`root`&&!l&&!u[e]&&o,...e!==`root`&&!u[e]&&o,..._,...b&&!s&&{as:b},...b&&s&&{component:b},ref:y},i)]}function ne(e){return r(`MuiSvgIcon`,e)}a(`MuiSvgIcon`,[`root`,`colorPrimary`,`colorSecondary`,`colorAction`,`colorError`,`colorDisabled`,`fontSizeInherit`,`fontSizeSmall`,`fontSizeMedium`,`fontSizeLarge`]);var re=e=>{let{color:t,fontSize:n,classes:r}=e,i={root:[`root`,t!==`inherit`&&`color${d(t)}`,`fontSize${d(n)}`]};return o(i,ne,r)},ie=c(`svg`,{name:`MuiSvgIcon`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,n.color!==`inherit`&&t[`color${d(n.color)}`],t[`fontSize${d(n.fontSize)}`]]}})(s(({theme:e})=>({userSelect:`none`,width:`1em`,height:`1em`,display:`inline-block`,flexShrink:0,...p(e,`fill`,{duration:(e.vars??e).transitions?.duration?.shorter}),variants:[{props:e=>!e.hasSvgAsChild,style:{fill:`currentColor`}},{props:{fontSize:`inherit`},style:{fontSize:`inherit`}},{props:{fontSize:`small`},style:{fontSize:e.typography?.pxToRem?.(20)||`1.25rem`}},{props:{fontSize:`medium`},style:{fontSize:e.typography?.pxToRem?.(24)||`1.5rem`}},{props:{fontSize:`large`},style:{fontSize:e.typography?.pxToRem?.(35)||`2.1875rem`}},...Object.entries((e.vars??e).palette).filter(([,e])=>e&&e.main).map(([t])=>({props:{color:t},style:{color:(e.vars??e).palette?.[t]?.main}})),{props:{color:`action`},style:{color:(e.vars??e).palette?.action?.active}},{props:{color:`disabled`},style:{color:(e.vars??e).palette?.action?.disabled}},{props:{color:`inherit`},style:{color:void 0}}]}))),R=b.forwardRef(function(e,t){let n=l({props:e,name:`MuiSvgIcon`}),{children:r,className:a,color:o=`inherit`,component:s=`svg`,fontSize:c=`medium`,htmlColor:u,inheritViewBox:d=!1,titleAccess:f,viewBox:p=`0 0 24 24`,...m}=n,h=b.isValidElement(r)&&r.type===`svg`,g={...n,color:o,component:s,fontSize:c,instanceFontSize:e.fontSize,inheritViewBox:d,viewBox:p,hasSvgAsChild:h},_={};d||(_.viewBox=p);let v=re(g);return(0,x.jsxs)(ie,{as:s,className:i(v.root,a),focusable:`false`,color:u,"aria-hidden":!f||void 0,role:f?`img`:void 0,ref:t,..._,...m,...h&&r.props,ownerState:g,children:[h?r.props.children:r,f?(0,x.jsx)(`title`,{children:f}):null]})});R.muiName=`SvgIcon`;function z(e,t){function n(t,n){return(0,x.jsx)(R,{"data-testid":void 0,ref:n,...t,children:e})}return n.muiName=R.muiName,b.memo(b.forwardRef(n))}function B(e,t){if(!e||!t)return!1;if(e.contains(t))return!0;let n=t.getRootNode?.();if(n&&n instanceof ShadowRoot){let n=t;for(;n;){if(e===n)return!0;n=n.parentNode??n.host??null}}return!1}var ae=B;function V(e,t){typeof e==`function`?e(t):e&&(e.current=t)}var oe=E,se=O;function ce(e){return r(`MuiIconButton`,e)}var H=a(`MuiIconButton`,[`root`,`disabled`,`colorInherit`,`colorPrimary`,`colorSecondary`,`colorError`,`colorInfo`,`colorSuccess`,`colorWarning`,`edgeStart`,`edgeEnd`,`sizeSmall`,`sizeMedium`,`sizeLarge`,`loading`,`loadingIndicator`,`loadingWrapper`]),le=e=>{let{classes:t,disabled:n,color:r,edge:i,size:a,loading:s}=e,c={root:[`root`,s&&`loading`,n&&`disabled`,r!=="default"&&`color${d(r)}`,i&&`edge${d(i)}`,`size${d(a)}`],loadingIndicator:[`loadingIndicator`],loadingWrapper:[`loadingWrapper`]};return o(c,ce,t)},ue=c(g,{name:`MuiIconButton`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,n.loading&&t.loading,n.color!=="default"&&t[`color${d(n.color)}`],n.edge&&t[`edge${d(n.edge)}`],t[`size${d(n.size)}`]]}})(s(({theme:e})=>({textAlign:`center`,flex:`0 0 auto`,fontSize:e.typography.pxToRem(24),padding:8,borderRadius:`50%`,color:(e.vars||e).palette.action.active,...p(e,`background-color`,{duration:e.transitions.duration.shortest}),variants:[{props:e=>!e.disableRipple,style:{"--IconButton-hoverBg":e.alpha((e.vars||e).palette.action.active,(e.vars||e).palette.action.hoverOpacity),"&:hover":{backgroundColor:`var(--IconButton-hoverBg)`,"@media (hover: none)":{backgroundColor:`transparent`}}}},{props:{edge:`start`},style:{marginLeft:-12}},{props:{edge:`start`,size:`small`},style:{marginLeft:-3}},{props:{edge:`end`},style:{marginRight:-12}},{props:{edge:`end`,size:`small`},style:{marginRight:-3}}]})),s(({theme:e})=>({variants:[{props:{color:`inherit`},style:{color:`inherit`}},...Object.entries(e.palette).filter(_()).map(([t])=>({props:{color:t},style:{color:(e.vars||e).palette[t].main,"--IconButton-hoverBg":e.alpha((e.vars||e).palette[t].main,(e.vars||e).palette.action.hoverOpacity)}})),{props:{size:`small`},style:{padding:5,fontSize:e.typography.pxToRem(18)}},{props:{size:`large`},style:{padding:12,fontSize:e.typography.pxToRem(28)}}],[`&.${H.disabled}`]:{backgroundColor:`transparent`,color:(e.vars||e).palette.action.disabled},[`&.${H.loading}`]:{color:`transparent`}}))),de=c(`span`,{name:`MuiIconButton`,slot:`LoadingIndicator`})(({theme:e})=>({display:`none`,position:`absolute`,visibility:`visible`,top:`50%`,left:`50%`,transform:`translate(-50%, -50%)`,color:(e.vars||e).palette.action.disabled,variants:[{props:{loading:!0},style:{display:`flex`}}]})),U=b.forwardRef(function(e,t){let n=l({props:e,name:`MuiIconButton`}),{edge:r=!1,children:a,className:o,color:s=`default`,disabled:c=!1,disableFocusRipple:u=!1,size:d=`medium`,id:f,loading:p=null,loadingIndicator:g,..._}=n,v=h(f),y=g??(0,x.jsx)(m,{"aria-labelledby":v,color:`inherit`,size:16}),b={...n,edge:r,color:s,disabled:c,disableFocusRipple:u,loading:p,loadingIndicator:y,size:d},S=le(b);return(0,x.jsxs)(ue,{id:p?v:f,className:i(S.root,o),centerRipple:!0,internalNativeButton:!0,focusRipple:!u,disabled:c||p,ref:t,..._,ownerState:b,children:[typeof p==`boolean`&&(0,x.jsx)(`span`,{className:S.loadingWrapper,style:{display:`contents`},children:(0,x.jsx)(de,{className:S.loadingIndicator,ownerState:b,children:p&&y})}),a]})}),W=b.createContext(void 0);function G(){let e=b.useContext(W);if(e===void 0)throw Error(`MUI: RovingTabIndexContext is missing. Roving tab index items must be placed within a roving tab index provider.`);return e}var fe=Object.is;function pe(e,t){if(e===t)return!0;if(!(e instanceof Object)||!(t instanceof Object))return!1;let n=0,r=0;for(let r in e)if(n+=1,!fe(e[r],t[r])||!(r in t))return!1;for(let e in t)r+=1;return n===r}var me=[`ArrowRight`,`ArrowLeft`,`ArrowUp`,`ArrowDown`,`Home`,`End`];function he(e){let{activeItemId:t,getDefaultActiveItemId:n,orientation:r,isRtl:i=!1,isItemFocusable:a=Ce,wrap:o=!0}=e,[s,c]=b.useState(t),[l,u]=b.useState(t),d=s;t!==l&&(u(t),t!==void 0&&t!==s&&(d=t,c(t)));let f=b.useRef(null),p=b.useRef(new Map),[m,h]=b.useState(0),g=b.useMemo(()=>X(p.current),[m]),_=K(d,g,a,n),y=b.useRef(_);y.current=_;let x=b.useCallback(()=>{let e=X(p.current);return ye(e,K(y.current,e,a,n))},[n,a]),S=b.useCallback(()=>p.current,[]),C=v(e=>{pe(p.current.get(e.id)??null,e)||(p.current.set(e.id,e),h(e=>e+1))}),w=v(e=>{p.current.delete(e)&&h(e=>e+1)}),T=v(e=>{c(e)}),E=b.useCallback(e=>y.current===e,[]),O=b.useCallback((e,t,n,r)=>{let i=J(Z(p.current),e,t,n,r??a);return i?(i.element?.focus(),c(i.id),i):null},[a]),k=b.useCallback((e,t,n)=>({onFocus:e=>{t?.(e);let n=Z(p.current),r=xe(n,e.target);r!==-1&&c(n[r].id)},onKeyDown:e=>{if(n?.(e),e.defaultPrevented||e.altKey||e.shiftKey||e.ctrlKey||e.metaKey||!me.includes(e.key))return;let t=r===`horizontal`?`ArrowLeft`:`ArrowUp`,a=r===`horizontal`?`ArrowRight`:`ArrowDown`;r===`horizontal`&&i&&(t=`ArrowRight`,a=`ArrowLeft`);let s=Z(p.current),c=j(D(f.current)),l=c===f.current,u=q(s,c,y.current),d=`next`;switch(e.key){case t:d=`previous`,e.preventDefault(),l&&(u=s.length);break;case a:e.preventDefault(),l&&(u=-1);break;case`Home`:e.preventDefault(),u=-1;break;case`End`:e.preventDefault(),d=`previous`,u=s.length;break;default:return}O(u,d,o)},ref:Te(e,e=>{f.current=e})}),[O,i,r,o]),A=b.useCallback(e=>{let t=Z(p.current),n=j(D(f.current)),r=n===f.current?-1:q(t,n,y.current);return O(r,`next`,!0,e)?.id??null},[O]);return b.useMemo(()=>({activeItemId:_,focusNext:A,getActiveItem:x,getContainerProps:k,getItemMap:S,isItemActive:E,registerItem:C,setActiveItemId:T,unregisterItem:w}),[_,A,x,k,S,E,C,T,w])}function ge(e){let{activeItemId:t,registerItem:n,unregisterItem:r}=G(),i=b.useRef(null),a=b.useMemo(()=>({disabled:e.disabled??!1,element:null,focusableWhenDisabled:e.focusableWhenDisabled??!1,id:e.id,selected:e.selected??!1,textValue:e.textValue}),[e.disabled,e.focusableWhenDisabled,e.id,e.selected,e.textValue]),o=b.useRef(a);o.current=a;let s=b.useCallback(t=>{if(i.current=t,t==null){queueMicrotask(()=>{i.current??r(e.id)});return}n({...o.current,element:t})},[e.id,n,r]),c=f(e.ref,s);return u(()=>{i.current&&n({...a,element:i.current})},[a,n]),u(()=>{let t=e.id;return()=>{r(t)}},[e.id,r]),{ref:c,tabIndex:t===e.id?0:-1}}function K(e,t,n,r){return e==null?ve(t,n,r):_e(e,t,n)}function _e(e,t,n){let r=be(t,e);return r===-1?Y(t,n):n(t[r])?t[r].id:J(t,r,`next`,!1,n)?.id??null}function ve(e,t,n){let r=n?.(e);if(r!=null){let n=ye(e,r);if(n&&t(n))return n.id}return Y(e,t)}function q(e,t,n){if(t){let n=xe(e,t);if(n!==-1)return n}return be(e,n)}function J(e,t,n,r,i){let a=e.length-1;if(a===-1)return null;let o=!1,s=Se(t,a,n,r),c=s;for(;s!==-1;){if(s===c){if(o)return null;o=!0}let t=e[s];if(!t||!i(t))s=Se(s,a,n,r);else return t}return null}function Y(e,t){return e.find(e=>t(e))?.id??null}function ye(e,t){return t==null?null:e.find(e=>e.id===t)??null}function be(e,t){return t==null?-1:e.findIndex(e=>e.id===t)}function xe(e,t){return t?e.findIndex(e=>e.element===t||e.element?.contains(t)):-1}function X(e){let t=Array.from(e.values());if(t.every(e=>e.element==null))return t;let n=t.filter(Q).sort((e,t)=>we(e.element,t.element)),r=t.filter(e=>!Q(e));return[...n,...r]}function Z(e){return X(e).filter(Q)}function Se(e,t,n,r=!0){return n===`next`?e===t?r?0:-1:e+1:e===0?r?t:-1:e-1}function Ce(e){return e.element?e.focusableWhenDisabled?!0:!e.disabled&&!e.element.hasAttribute(`disabled`)&&e.element.getAttribute(`aria-disabled`)!==`true`&&e.element.hasAttribute(`tabindex`):!1}function Q(e){return e.element!=null&&e.element.isConnected}function we(e,t){if(e===t)return 0;let n=e.compareDocumentPosition(t);return n&Node.DOCUMENT_POSITION_FOLLOWING||n&Node.DOCUMENT_POSITION_CONTAINED_BY?-1:n&Node.DOCUMENT_POSITION_PRECEDING||n&Node.DOCUMENT_POSITION_CONTAINS?1:0}function Te(...e){return t=>{e.forEach(e=>{V(e??null,t)})}}function Ee(e){let{elementType:t,externalSlotProps:n,ownerState:r,skipResolvingSlotProps:i=!1,...a}=e,o=i?{}:N(n,r),{props:s,internalRef:c}=te({...a,externalSlotProps:o}),l=f(c,o?.ref,e.additionalProps?.ref);return M(t,{...s,ref:l},r)}function De(e){return r(`MuiAlert`,e)}var Oe=a(`MuiAlert`,[`root`,`action`,`icon`,`message`,`filled`,`colorSuccess`,`colorInfo`,`colorWarning`,`colorError`,`outlined`,`standard`]),ke=z((0,x.jsx)(`path`,{d:`M20,12A8,8 0 0,1 12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4C12.76,4 13.5,4.11 14.2, 4.31L15.77,2.74C14.61,2.26 13.34,2 12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0, 0 22,12M7.91,10.08L6.5,11.5L11,16L21,6L19.59,4.58L11,13.17L7.91,10.08Z`}),`SuccessOutlined`),Ae=z((0,x.jsx)(`path`,{d:`M12 5.99L19.53 19H4.47L12 5.99M12 2L1 21h22L12 2zm1 14h-2v2h2v-2zm0-6h-2v4h2v-4z`}),`ReportProblemOutlined`),je=z((0,x.jsx)(`path`,{d:`M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z`}),`ErrorOutline`),Me=z((0,x.jsx)(`path`,{d:`M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20, 12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10, 10 0 0,0 12,2M11,17H13V11H11V17Z`}),`InfoOutlined`),Ne=z((0,x.jsx)(`path`,{d:`M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z`}),`Close`),Pe=e=>{let{variant:t,color:n,severity:r,classes:i}=e,a={root:[`root`,`color${d(n||r)}`,`${t}`],icon:[`icon`],message:[`message`],action:[`action`]};return o(a,De,i)},Fe=c(y,{name:`MuiAlert`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,t[n.variant]]}})(s(({theme:e})=>{let t=e.palette.mode===`light`?e.darken:e.lighten,n=e.palette.mode===`light`?e.lighten:e.darken;return{...e.typography.body2,backgroundColor:`transparent`,display:`flex`,padding:`6px 16px`,variants:[...Object.entries(e.palette).filter(_([`light`])).map(([r])=>({props:{colorSeverity:r,variant:`standard`},style:{color:e.vars?e.vars.palette.Alert[`${r}Color`]:t(e.palette[r].light,.6),backgroundColor:e.vars?e.vars.palette.Alert[`${r}StandardBg`]:n(e.palette[r].light,.9),[`& .${Oe.icon}`]:e.vars?{color:e.vars.palette.Alert[`${r}IconColor`]}:{color:e.palette[r].main}}})),...Object.entries(e.palette).filter(_([`light`])).map(([n])=>({props:{colorSeverity:n,variant:`outlined`},style:{color:e.vars?e.vars.palette.Alert[`${n}Color`]:t(e.palette[n].light,.6),border:`1px solid ${(e.vars||e).palette[n].light}`,[`& .${Oe.icon}`]:e.vars?{color:e.vars.palette.Alert[`${n}IconColor`]}:{color:e.palette[n].main}}})),...Object.entries(e.palette).filter(_([`dark`])).map(([t])=>({props:{colorSeverity:t,variant:`filled`},style:{fontWeight:e.typography.fontWeightMedium,...e.vars?{color:e.vars.palette.Alert[`${t}FilledColor`],backgroundColor:e.vars.palette.Alert[`${t}FilledBg`]}:{backgroundColor:e.palette.mode===`dark`?e.palette[t].dark:e.palette[t].main,color:e.palette.getContrastText(e.palette[t].main)}}}))]}})),Ie=c(`div`,{name:`MuiAlert`,slot:`Icon`})({marginRight:12,padding:`7px 0`,display:`flex`,fontSize:22,opacity:.9}),Le=c(`div`,{name:`MuiAlert`,slot:`Message`})({padding:`8px 0`,minWidth:0,overflow:`auto`}),Re=c(`div`,{name:`MuiAlert`,slot:`Action`})({display:`flex`,alignItems:`flex-start`,padding:`4px 0 0 16px`,marginLeft:`auto`,marginRight:-8}),$={success:(0,x.jsx)(ke,{fontSize:`inherit`}),warning:(0,x.jsx)(Ae,{fontSize:`inherit`}),error:(0,x.jsx)(je,{fontSize:`inherit`}),info:(0,x.jsx)(Me,{fontSize:`inherit`})},ze=b.forwardRef(function(e,t){let n=l({props:e,name:`MuiAlert`}),{action:r,children:a,className:o,closeText:s=`Close`,color:c,icon:u,iconMapping:d=$,onClose:f,role:p=`alert`,severity:m=`success`,slotProps:h={},slots:g={},variant:_=`standard`,...v}=n,y={...n,color:c,severity:m,variant:_,colorSeverity:c||m},b=Pe(y),S={slots:g,slotProps:h},[C,w]=L(`root`,{ref:t,shouldForwardComponentProp:!0,className:i(b.root,o),elementType:Fe,externalForwardedProps:{...S,...v},ownerState:y,additionalProps:{role:p,elevation:0}}),[T,E]=L(`icon`,{className:b.icon,elementType:Ie,externalForwardedProps:S,ownerState:y}),[D,O]=L(`message`,{className:b.message,elementType:Le,externalForwardedProps:S,ownerState:y}),[k,A]=L(`action`,{className:b.action,elementType:Re,externalForwardedProps:S,ownerState:y}),[j,ee]=L(`closeButton`,{elementType:U,externalForwardedProps:S,ownerState:y}),[M,N]=L(`closeIcon`,{elementType:Ne,externalForwardedProps:S,ownerState:y});return(0,x.jsxs)(C,{...w,children:[u===!1?null:(0,x.jsx)(T,{...E,children:u||d[m]||$[m]}),(0,x.jsx)(D,{...O,children:a}),r==null?null:(0,x.jsx)(k,{...A,children:r}),r==null&&f?(0,x.jsx)(k,{...A,children:(0,x.jsx)(j,{size:`small`,"aria-label":s,title:s,color:`inherit`,onClick:f,...ee,children:(0,x.jsx)(M,{fontSize:`small`,...N})})}):null]})});export{D as C,w as D,C as E,O as S,T,F as _,he as a,A as b,U as c,V as d,ae as f,L as g,R as h,ge as i,se as l,z as m,Ee as n,W as o,B as p,Ce as r,G as s,ze as t,oe as u,P as v,E as w,k as x,ee as y};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{U as t,b as n,d as r,f as i,u as a}from"./useTheme-_ESOj7MI.js";import{A as o,C as s,D as c,E as l,O as u,P as d,S as f,_ as p,a as m,i as h,o as g,p as _}from"./ui-preferences-DiddStu0.js";var v=e(t(),1);function y(e){return r(`MuiButton`,e)}var b=a(`MuiButton`,`root.text.outlined.contained.disableElevation.focusVisible.disabled.colorInherit.colorPrimary.colorSecondary.colorSuccess.colorError.colorInfo.colorWarning.sizeMedium.sizeSmall.sizeLarge.fullWidth.startIcon.endIcon.icon.loading.loadingWrapper.loadingIconPlaceholder.loadingIndicator.loadingPositionCenter.loadingPositionStart.loadingPositionEnd`.split(`.`)),x=v.createContext({}),S=v.createContext(void 0),C=n(),w=e=>{let{color:t,disableElevation:n,fullWidth:r,size:i,variant:a,loading:s,loadingPosition:c,classes:l}=e,u={root:[`root`,s&&`loading`,a,`size${f(i)}`,`color${f(t)}`,n&&`disableElevation`,r&&`fullWidth`,s&&`loadingPosition${f(c)}`],startIcon:[`icon`,`startIcon`],endIcon:[`icon`,`endIcon`],loadingIndicator:[`loadingIndicator`],loadingWrapper:[`loadingWrapper`]},d=o(u,y,l);return{...l,...d}},T=[{props:{size:`small`},style:{"& > *:nth-of-type(1)":{fontSize:18}}},{props:{size:`medium`},style:{"& > *:nth-of-type(1)":{fontSize:20}}},{props:{size:`large`},style:{"& > *:nth-of-type(1)":{fontSize:22}}}],E=c(g,{shouldForwardProp:e=>u(e)||e===`classes`,name:`MuiButton`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,t[n.variant],t[`size${f(n.size)}`],n.color===`inherit`&&t.colorInherit,n.disableElevation&&t.disableElevation,n.fullWidth&&t.fullWidth,n.loading&&t.loading]}})(s(({theme:e})=>{let t=e.palette.mode===`light`?e.palette.grey[300]:e.palette.grey[800],n=e.palette.mode===`light`?e.palette.grey.A100:e.palette.grey[700];return{...e.typography.button,minWidth:64,padding:`6px 16px`,border:0,borderRadius:(e.vars||e).shape.borderRadius,...p(e,[`background-color`,`box-shadow`,`border-color`,`color`],{duration:e.transitions.duration.short}),"&:hover":{textDecoration:`none`},[`&.${b.disabled}`]:{color:(e.vars||e).palette.action.disabled},variants:[{props:{variant:`contained`},style:{color:`var(--variant-containedColor)`,backgroundColor:`var(--variant-containedBg)`,boxShadow:(e.vars||e).shadows[2],"&:hover":{boxShadow:(e.vars||e).shadows[4],"@media (hover: none)":{boxShadow:(e.vars||e).shadows[2]}},"&:active":{boxShadow:(e.vars||e).shadows[8]},[`&.${b.focusVisible}`]:{boxShadow:(e.vars||e).shadows[6]},[`&.${b.disabled}`]:{color:(e.vars||e).palette.action.disabled,boxShadow:(e.vars||e).shadows[0],backgroundColor:(e.vars||e).palette.action.disabledBackground}}},{props:{variant:`outlined`},style:{padding:`5px 15px`,border:`1px solid currentColor`,borderColor:`var(--variant-outlinedBorder, currentColor)`,backgroundColor:`var(--variant-outlinedBg)`,color:`var(--variant-outlinedColor)`,[`&.${b.disabled}`]:{border:`1px solid ${(e.vars||e).palette.action.disabledBackground}`}}},{props:{variant:`text`},style:{padding:`6px 8px`,color:`var(--variant-textColor)`,backgroundColor:`var(--variant-textBg)`}},...Object.entries(e.palette).filter(_()).map(([t])=>({props:{color:t},style:{"--variant-textColor":(e.vars||e).palette[t].main,"--variant-outlinedColor":(e.vars||e).palette[t].main,"--variant-outlinedBorder":e.alpha((e.vars||e).palette[t].main,.5),"--variant-containedColor":(e.vars||e).palette[t].contrastText,"--variant-containedBg":(e.vars||e).palette[t].main,"@media (hover: hover)":{"&:hover":{"--variant-containedBg":(e.vars||e).palette[t].dark,"--variant-textBg":e.alpha((e.vars||e).palette[t].main,(e.vars||e).palette.action.hoverOpacity),"--variant-outlinedBorder":(e.vars||e).palette[t].main,"--variant-outlinedBg":e.alpha((e.vars||e).palette[t].main,(e.vars||e).palette.action.hoverOpacity)}}}})),{props:{color:`inherit`},style:{color:`inherit`,borderColor:`currentColor`,"--variant-containedBg":e.vars?e.vars.palette.Button.inheritContainedBg:t,"@media (hover: hover)":{"&:hover":{"--variant-containedBg":e.vars?e.vars.palette.Button.inheritContainedHoverBg:n,"--variant-textBg":e.alpha((e.vars||e).palette.text.primary,(e.vars||e).palette.action.hoverOpacity),"--variant-outlinedBg":e.alpha((e.vars||e).palette.text.primary,(e.vars||e).palette.action.hoverOpacity)}}}},{props:{size:`small`,variant:`text`},style:{padding:`4px 5px`,fontSize:e.typography.pxToRem(13)}},{props:{size:`large`,variant:`text`},style:{padding:`8px 11px`,fontSize:e.typography.pxToRem(15)}},{props:{size:`small`,variant:`outlined`},style:{padding:`3px 9px`,fontSize:e.typography.pxToRem(13)}},{props:{size:`large`,variant:`outlined`},style:{padding:`7px 21px`,fontSize:e.typography.pxToRem(15)}},{props:{size:`small`,variant:`contained`},style:{padding:`4px 10px`,fontSize:e.typography.pxToRem(13)}},{props:{size:`large`,variant:`contained`},style:{padding:`8px 22px`,fontSize:e.typography.pxToRem(15)}},{props:{disableElevation:!0},style:{boxShadow:`none`,"&:hover":{boxShadow:`none`},[`&.${b.focusVisible}`]:{boxShadow:`none`},"&:active":{boxShadow:`none`},[`&.${b.disabled}`]:{boxShadow:`none`}}},{props:{fullWidth:!0},style:{width:`100%`}},{props:{loadingPosition:`center`},style:{...p(e,[`background-color`,`box-shadow`,`border-color`],{duration:e.transitions.duration.short}),[`&.${b.loading}`]:{color:`transparent`}}}]}})),D=c(`span`,{name:`MuiButton`,slot:`StartIcon`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.startIcon,n.loading&&t.startIconLoadingStart]}})(({theme:e})=>({display:`inherit`,alignItems:`center`,marginRight:8,marginLeft:-4,"&::before":{content:`"\\200b"`,width:0,overflow:`hidden`},variants:[{props:{size:`small`},style:{marginLeft:-2}},{props:{loadingPosition:`start`,loading:!0},style:{...p(e,[`opacity`],{duration:e.transitions.duration.short}),opacity:0}},{props:{loadingPosition:`start`,loading:!0,fullWidth:!0},style:{marginRight:-8}},...T]})),O=c(`span`,{name:`MuiButton`,slot:`EndIcon`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.endIcon,n.loading&&t.endIconLoadingEnd]}})(({theme:e})=>({display:`inherit`,marginRight:-4,marginLeft:8,variants:[{props:{size:`small`},style:{marginRight:-2}},{props:{loadingPosition:`end`,loading:!0},style:{...p(e,[`opacity`],{duration:e.transitions.duration.short}),opacity:0}},{props:{loadingPosition:`end`,loading:!0,fullWidth:!0},style:{marginLeft:-8}},...T]})),k=c(`span`,{name:`MuiButton`,slot:`LoadingIndicator`})(({theme:e})=>({display:`none`,position:`absolute`,visibility:`visible`,variants:[{props:{loading:!0},style:{display:`flex`}},{props:{loadingPosition:`start`},style:{left:14}},{props:{loadingPosition:`start`,size:`small`},style:{left:10}},{props:{variant:`text`,loadingPosition:`start`},style:{left:6}},{props:{loadingPosition:`center`},style:{left:`50%`,transform:`translate(-50%)`,color:(e.vars||e).palette.action.disabled}},{props:{loadingPosition:`end`},style:{right:14}},{props:{loadingPosition:`end`,size:`small`},style:{right:10}},{props:{variant:`text`,loadingPosition:`end`},style:{right:6}},{props:{loadingPosition:`start`,fullWidth:!0},style:{position:`relative`,left:-10}},{props:{loadingPosition:`end`,fullWidth:!0},style:{position:`relative`,right:-10}}]})),A=c(`span`,{name:`MuiButton`,slot:`LoadingIconPlaceholder`})({display:`inline-block`,width:`1em`,height:`1em`}),j=v.forwardRef(function(e,t){let n=v.useContext(x),r=v.useContext(S),a=d(n,e),o=l({props:a,name:`MuiButton`}),{children:s,color:c=`primary`,component:u=`button`,className:f,disabled:p=!1,disableElevation:g=!1,disableFocusRipple:_=!1,endIcon:y,focusVisibleClassName:b,fullWidth:T=!1,id:j,loading:M=null,loadingIndicator:N,loadingPosition:P=`center`,size:F=`medium`,startIcon:I,type:L,variant:R=`text`,...z}=o,B=h(j),V=N??(0,C.jsx)(m,{"aria-labelledby":B,color:`inherit`,size:16}),H={...o,color:c,component:u,disabled:p,disableElevation:g,disableFocusRipple:_,fullWidth:T,loading:M,loadingIndicator:V,loadingPosition:P,size:F,type:L,variant:R},U=w(H),W=(I||M&&P===`start`)&&(0,C.jsx)(D,{className:U.startIcon,ownerState:H,children:I||(0,C.jsx)(A,{className:U.loadingIconPlaceholder,ownerState:H})}),G=(y||M&&P===`end`)&&(0,C.jsx)(O,{className:U.endIcon,ownerState:H,children:y||(0,C.jsx)(A,{className:U.loadingIconPlaceholder,ownerState:H})}),K=r||``,q=typeof M==`boolean`?(0,C.jsx)(`span`,{className:U.loadingWrapper,style:{display:`contents`},children:M&&(0,C.jsx)(k,{className:U.loadingIndicator,ownerState:H,children:V})}):null,{root:J,...Y}=U;return(0,C.jsxs)(E,{ownerState:H,className:i(n.className,U.root,f,K),component:u,disabled:p||M,focusRipple:!_,focusVisibleClassName:i(U.focusVisible,b),ref:t,internalNativeButton:!0,type:L,id:M?B:j,...z,classes:Y,children:[W,P!==`end`&&q,s,P===`end`&&q,G]})});export{j as t};
|