@stigmer/react 3.1.6 → 3.1.8
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/agent/AgentDetailView.d.ts +9 -1
- package/agent/AgentDetailView.d.ts.map +1 -1
- package/agent/AgentDetailView.js +15 -4
- package/agent/AgentDetailView.js.map +1 -1
- package/environment/EnvironmentListPanel.d.ts.map +1 -1
- package/environment/EnvironmentListPanel.js +11 -3
- package/environment/EnvironmentListPanel.js.map +1 -1
- package/environment/EnvironmentVariableEditor.d.ts.map +1 -1
- package/environment/EnvironmentVariableEditor.js +9 -3
- package/environment/EnvironmentVariableEditor.js.map +1 -1
- package/environment/index.d.ts +1 -0
- package/environment/index.d.ts.map +1 -1
- package/environment/index.js +1 -0
- package/environment/index.js.map +1 -1
- package/environment/shareRestriction.d.ts +13 -0
- package/environment/shareRestriction.d.ts.map +1 -0
- package/environment/shareRestriction.js +15 -0
- package/environment/shareRestriction.js.map +1 -0
- package/execution/ToolCallItem.d.ts.map +1 -1
- package/execution/ToolCallItem.js +12 -0
- package/execution/ToolCallItem.js.map +1 -1
- package/execution/ToolRunGroup.js +4 -0
- package/execution/ToolRunGroup.js.map +1 -1
- package/execution/WriteBackCard.d.ts +14 -5
- package/execution/WriteBackCard.d.ts.map +1 -1
- package/execution/WriteBackCard.js +103 -32
- package/execution/WriteBackCard.js.map +1 -1
- package/execution/WriteBacksWidget.d.ts +1 -1
- package/execution/WriteBacksWidget.js +2 -2
- package/execution/WriteBacksWidget.js.map +1 -1
- package/execution/index.d.ts +2 -0
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +1 -0
- package/execution/index.js.map +1 -1
- package/execution/write-back-utils.d.ts +57 -0
- package/execution/write-back-utils.d.ts.map +1 -0
- package/execution/write-back-utils.js +81 -0
- package/execution/write-back-utils.js.map +1 -0
- package/index.d.ts +6 -2
- package/index.d.ts.map +1 -1
- package/index.js +6 -1
- package/index.js.map +1 -1
- package/internal/dev/dom-counter.d.ts.map +1 -1
- package/internal/dev/dom-counter.js +2 -2
- package/internal/dev/dom-counter.js.map +1 -1
- package/internal/dev/enabled.d.ts +7 -0
- package/internal/dev/enabled.d.ts.map +1 -0
- package/internal/dev/enabled.js +38 -0
- package/internal/dev/enabled.js.map +1 -0
- package/internal/dev/profiler-wrapper.d.ts +3 -3
- package/internal/dev/profiler-wrapper.d.ts.map +1 -1
- package/internal/dev/profiler-wrapper.js +5 -5
- package/internal/dev/profiler-wrapper.js.map +1 -1
- package/internal/dev/use-key-stability.d.ts.map +1 -1
- package/internal/dev/use-key-stability.js +2 -2
- package/internal/dev/use-key-stability.js.map +1 -1
- package/internal/dev/use-render-tracer.d.ts +2 -2
- package/internal/dev/use-render-tracer.d.ts.map +1 -1
- package/internal/dev/use-render-tracer.js +4 -4
- package/internal/dev/use-render-tracer.js.map +1 -1
- package/internal/dev/use-stream-rate.d.ts +2 -1
- package/internal/dev/use-stream-rate.d.ts.map +1 -1
- package/internal/dev/use-stream-rate.js +4 -3
- package/internal/dev/use-stream-rate.js.map +1 -1
- package/library/ResourceVisibilityControl.d.ts +3 -0
- package/library/ResourceVisibilityControl.d.ts.map +1 -1
- package/library/ResourceVisibilityControl.js +22 -8
- package/library/ResourceVisibilityControl.js.map +1 -1
- package/library/useUpdateVisibility.d.ts +5 -3
- package/library/useUpdateVisibility.d.ts.map +1 -1
- package/library/useUpdateVisibility.js +7 -2
- package/library/useUpdateVisibility.js.map +1 -1
- package/library/visibilityLevels.d.ts +17 -0
- package/library/visibilityLevels.d.ts.map +1 -1
- package/library/visibilityLevels.js +32 -0
- package/library/visibilityLevels.js.map +1 -1
- package/mcp-server/McpServerConnectDialog.d.ts.map +1 -1
- package/mcp-server/McpServerConnectDialog.js +7 -3
- package/mcp-server/McpServerConnectDialog.js.map +1 -1
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +6 -3
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/McpServerPicker.d.ts.map +1 -1
- package/mcp-server/McpServerPicker.js +3 -1
- package/mcp-server/McpServerPicker.js.map +1 -1
- package/mcp-server/OAuthRequiredNotice.d.ts +29 -0
- package/mcp-server/OAuthRequiredNotice.d.ts.map +1 -0
- package/mcp-server/OAuthRequiredNotice.js +29 -0
- package/mcp-server/OAuthRequiredNotice.js.map +1 -0
- package/mcp-server/StdioSandboxNotice.d.ts +43 -0
- package/mcp-server/StdioSandboxNotice.d.ts.map +1 -0
- package/mcp-server/StdioSandboxNotice.js +45 -0
- package/mcp-server/StdioSandboxNotice.js.map +1 -0
- package/mcp-server/useMcpServerCredentials.d.ts +12 -0
- package/mcp-server/useMcpServerCredentials.d.ts.map +1 -1
- package/mcp-server/useMcpServerCredentials.js +12 -4
- package/mcp-server/useMcpServerCredentials.js.map +1 -1
- package/package.json +4 -4
- package/session/NewSessionViewer.d.ts +11 -1
- package/session/NewSessionViewer.d.ts.map +1 -1
- package/session/NewSessionViewer.js +28 -8
- package/session/NewSessionViewer.js.map +1 -1
- package/session/SessionViewer.d.ts +9 -2
- package/session/SessionViewer.d.ts.map +1 -1
- package/session/SessionViewer.js +26 -12
- package/session/SessionViewer.js.map +1 -1
- package/session/audience.d.ts +12 -4
- package/session/audience.d.ts.map +1 -1
- package/session/facets/ChangesTab.d.ts.map +1 -1
- package/session/facets/ChangesTab.js +3 -1
- package/session/facets/ChangesTab.js.map +1 -1
- package/session/useNewSessionFlow.d.ts +12 -0
- package/session/useNewSessionFlow.d.ts.map +1 -1
- package/session/useNewSessionFlow.js +13 -1
- package/session/useNewSessionFlow.js.map +1 -1
- package/session/useSessionPageFlow.d.ts +13 -0
- package/session/useSessionPageFlow.d.ts.map +1 -1
- package/session/useSessionPageFlow.js +7 -2
- package/session/useSessionPageFlow.js.map +1 -1
- package/sharing/ShareAgentDialog.d.ts +55 -0
- package/sharing/ShareAgentDialog.d.ts.map +1 -0
- package/sharing/ShareAgentDialog.js +393 -0
- package/sharing/ShareAgentDialog.js.map +1 -0
- package/sharing/SharedAgentChat.d.ts +84 -0
- package/sharing/SharedAgentChat.d.ts.map +1 -0
- package/sharing/SharedAgentChat.js +80 -0
- package/sharing/SharedAgentChat.js.map +1 -0
- package/sharing/index.d.ts +16 -0
- package/sharing/index.d.ts.map +1 -0
- package/sharing/index.js +11 -0
- package/sharing/index.js.map +1 -0
- package/sharing/useRotateShareLink.d.ts +42 -0
- package/sharing/useRotateShareLink.d.ts.map +1 -0
- package/sharing/useRotateShareLink.js +55 -0
- package/sharing/useRotateShareLink.js.map +1 -0
- package/sharing/useShareAgent.d.ts +68 -0
- package/sharing/useShareAgent.d.ts.map +1 -0
- package/sharing/useShareAgent.js +41 -0
- package/sharing/useShareAgent.js.map +1 -0
- package/sharing/useShareToolReadiness.d.ts +48 -0
- package/sharing/useShareToolReadiness.d.ts.map +1 -0
- package/sharing/useShareToolReadiness.js +93 -0
- package/sharing/useShareToolReadiness.js.map +1 -0
- package/sharing/useSharedAgentProfile.d.ts +84 -0
- package/sharing/useSharedAgentProfile.d.ts.map +1 -0
- package/sharing/useSharedAgentProfile.js +72 -0
- package/sharing/useSharedAgentProfile.js.map +1 -0
- package/sharing/useUpdateAgentSharing.d.ts +86 -0
- package/sharing/useUpdateAgentSharing.d.ts.map +1 -0
- package/sharing/useUpdateAgentSharing.js +81 -0
- package/sharing/useUpdateAgentSharing.js.map +1 -0
- package/src/agent/AgentDetailView.tsx +28 -3
- package/src/environment/EnvironmentListPanel.tsx +47 -18
- package/src/environment/EnvironmentVariableEditor.tsx +27 -17
- package/src/environment/__tests__/shareRestriction.test.ts +35 -0
- package/src/environment/index.ts +5 -0
- package/src/environment/shareRestriction.ts +22 -0
- package/src/execution/ToolCallItem.tsx +19 -1
- package/src/execution/ToolRunGroup.tsx +4 -0
- package/src/execution/WriteBackCard.tsx +285 -88
- package/src/execution/WriteBacksWidget.tsx +5 -5
- package/src/execution/__tests__/ToolCallItem.test.tsx +51 -0
- package/src/execution/__tests__/ToolRunGroup.test.tsx +22 -0
- package/src/execution/__tests__/WriteBackCard.test.tsx +64 -10
- package/src/execution/__tests__/write-back-utils.test.ts +135 -0
- package/src/execution/index.ts +7 -0
- package/src/execution/write-back-utils.ts +107 -0
- package/src/index.ts +34 -0
- package/src/internal/dev/__tests__/use-key-stability.test.ts +4 -0
- package/src/internal/dev/__tests__/use-render-tracer.test.ts +4 -0
- package/src/internal/dev/dom-counter.ts +2 -3
- package/src/internal/dev/enabled.ts +39 -0
- package/src/internal/dev/profiler-wrapper.tsx +5 -6
- package/src/internal/dev/use-key-stability.ts +2 -3
- package/src/internal/dev/use-render-tracer.ts +4 -5
- package/src/internal/dev/use-stream-rate.ts +4 -4
- package/src/library/ResourceVisibilityControl.tsx +23 -7
- package/src/library/__tests__/visibilityLevels.test.ts +33 -0
- package/src/library/useUpdateVisibility.ts +9 -3
- package/src/library/visibilityLevels.ts +36 -0
- package/src/mcp-server/McpServerConnectDialog.tsx +23 -11
- package/src/mcp-server/McpServerDetailView.tsx +22 -9
- package/src/mcp-server/McpServerPicker.tsx +12 -9
- package/src/mcp-server/OAuthRequiredNotice.tsx +77 -0
- package/src/mcp-server/StdioSandboxNotice.tsx +98 -0
- package/src/mcp-server/__tests__/OAuthRequiredNotice.test.tsx +25 -0
- package/src/mcp-server/__tests__/StdioSandboxNotice.test.tsx +71 -0
- package/src/mcp-server/useMcpServerCredentials.ts +25 -4
- package/src/session/NewSessionViewer.tsx +67 -31
- package/src/session/SessionViewer.tsx +67 -36
- package/src/session/__tests__/audienceWiring.test.tsx +99 -0
- package/src/session/__tests__/useNewSessionFlow.test.tsx +75 -1
- package/src/session/__tests__/useSessionPageFlow.guest.test.tsx +112 -0
- package/src/session/audience.ts +12 -4
- package/src/session/facets/ChangesTab.tsx +6 -4
- package/src/session/useNewSessionFlow.ts +26 -1
- package/src/session/useSessionPageFlow.ts +24 -2
- package/src/sharing/ShareAgentDialog.tsx +1255 -0
- package/src/sharing/SharedAgentChat.tsx +283 -0
- package/src/sharing/__tests__/ShareAgentDialog.test.tsx +745 -0
- package/src/sharing/__tests__/SharedAgentChat.test.tsx +222 -0
- package/src/sharing/__tests__/useRotateShareLink.test.tsx +96 -0
- package/src/sharing/__tests__/useShareAgent.test.tsx +127 -0
- package/src/sharing/__tests__/useShareToolReadiness.test.tsx +182 -0
- package/src/sharing/__tests__/useSharedAgentProfile.test.tsx +201 -0
- package/src/sharing/__tests__/useUpdateAgentSharing.test.tsx +200 -0
- package/src/sharing/index.ts +30 -0
- package/src/sharing/useRotateShareLink.ts +76 -0
- package/src/sharing/useShareAgent.tsx +106 -0
- package/src/sharing/useShareToolReadiness.ts +129 -0
- package/src/sharing/useSharedAgentProfile.ts +131 -0
- package/src/sharing/useUpdateAgentSharing.ts +151 -0
- package/src/switch/Switch.tsx +92 -0
- package/src/switch/__tests__/Switch.test.tsx +88 -0
- package/src/switch/index.ts +2 -0
- package/styles.css +1 -1
- package/switch/Switch.d.ts +47 -0
- package/switch/Switch.d.ts.map +1 -0
- package/switch/Switch.js +36 -0
- package/switch/Switch.js.map +1 -0
- package/switch/index.d.ts +3 -0
- package/switch/index.d.ts.map +1 -0
- package/switch/index.js +2 -0
- package/switch/index.js.map +1 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* write-back-utils — the structured seam between the runner's raw
|
|
3
|
+
* `git diff --stat` text and the presentation layer. The parser must be
|
|
4
|
+
* strict: wrong numbers are worse than the raw-text fallback, so anything
|
|
5
|
+
* that is not the exact trailing summary line returns null.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect } from "vitest";
|
|
8
|
+
import { create } from "@bufbuild/protobuf";
|
|
9
|
+
import { WorkspaceWriteBackSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/writeback_pb";
|
|
10
|
+
import {
|
|
11
|
+
parseDiffStatSummary,
|
|
12
|
+
trailingDiffStatLine,
|
|
13
|
+
writeBackDisplayName,
|
|
14
|
+
} from "../write-back-utils";
|
|
15
|
+
|
|
16
|
+
describe("parseDiffStatSummary", () => {
|
|
17
|
+
it("parses the full three-segment summary line", () => {
|
|
18
|
+
expect(
|
|
19
|
+
parseDiffStatSummary(" 3 files changed, 42 insertions(+), 7 deletions(-)"),
|
|
20
|
+
).toEqual({ filesChanged: 3, insertions: 42, deletions: 7 });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("parses singular forms (1 file / 1 insertion / 1 deletion)", () => {
|
|
24
|
+
expect(
|
|
25
|
+
parseDiffStatSummary(" 1 file changed, 1 insertion(+), 1 deletion(-)"),
|
|
26
|
+
).toEqual({ filesChanged: 1, insertions: 1, deletions: 1 });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("parses an insertions-only summary (deletions segment omitted by git)", () => {
|
|
30
|
+
expect(parseDiffStatSummary(" 1 file changed, 55 insertions(+)")).toEqual({
|
|
31
|
+
filesChanged: 1,
|
|
32
|
+
insertions: 55,
|
|
33
|
+
deletions: 0,
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("parses a deletions-only summary (insertions segment omitted by git)", () => {
|
|
38
|
+
expect(parseDiffStatSummary(" 2 files changed, 9 deletions(-)")).toEqual({
|
|
39
|
+
filesChanged: 2,
|
|
40
|
+
insertions: 0,
|
|
41
|
+
deletions: 9,
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("parses a bare 'N file changed' summary with no count segments", () => {
|
|
46
|
+
expect(parseDiffStatSummary(" 1 file changed")).toEqual({
|
|
47
|
+
filesChanged: 1,
|
|
48
|
+
insertions: 0,
|
|
49
|
+
deletions: 0,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("reads the trailing line of a full --stat block, ignoring per-file lines", () => {
|
|
54
|
+
const stat = [
|
|
55
|
+
" notes.md | 55 ++++++++++",
|
|
56
|
+
" src/{old.ts => new.ts} | 5 +-",
|
|
57
|
+
" 2 files changed, 58 insertions(+), 2 deletions(-)",
|
|
58
|
+
].join("\n");
|
|
59
|
+
expect(parseDiffStatSummary(stat)).toEqual({
|
|
60
|
+
filesChanged: 2,
|
|
61
|
+
insertions: 58,
|
|
62
|
+
deletions: 2,
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("tolerates trailing whitespace/newlines after the summary line", () => {
|
|
67
|
+
expect(parseDiffStatSummary(" 1 file changed, 2 insertions(+)\n\n")).toEqual({
|
|
68
|
+
filesChanged: 1,
|
|
69
|
+
insertions: 2,
|
|
70
|
+
deletions: 0,
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("returns null for an empty or blank string", () => {
|
|
75
|
+
expect(parseDiffStatSummary("")).toBeNull();
|
|
76
|
+
expect(parseDiffStatSummary(" \n ")).toBeNull();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("returns null for unrecognized text rather than guessing", () => {
|
|
80
|
+
expect(parseDiffStatSummary(" changed")).toBeNull();
|
|
81
|
+
expect(parseDiffStatSummary("nothing to see here")).toBeNull();
|
|
82
|
+
// A per-file line with no trailing summary must not parse.
|
|
83
|
+
expect(parseDiffStatSummary(" notes.md | 55 +++")).toBeNull();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe("trailingDiffStatLine", () => {
|
|
88
|
+
it("returns the last non-empty line, trimmed", () => {
|
|
89
|
+
expect(trailingDiffStatLine(" a.ts | 1 +\n 1 file changed \n\n")).toBe(
|
|
90
|
+
"1 file changed",
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("returns null for blank input", () => {
|
|
95
|
+
expect(trailingDiffStatLine("")).toBeNull();
|
|
96
|
+
expect(trailingDiffStatLine(" \n ")).toBeNull();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe("writeBackDisplayName", () => {
|
|
101
|
+
it("prefers the configured workspace entry name", () => {
|
|
102
|
+
const wb = create(WorkspaceWriteBackSchema, {
|
|
103
|
+
workspaceEntryName: "acme/api",
|
|
104
|
+
pullRequestUrl: "https://github.com/other/repo/pull/1",
|
|
105
|
+
});
|
|
106
|
+
expect(writeBackDisplayName(wb)).toBe("acme/api");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Single-entry sessions can write back under an empty entry name (the
|
|
110
|
+
// runner's resolveEntry convention) — the repo identity from the PR URL is
|
|
111
|
+
// the next-most-honest label.
|
|
112
|
+
it("derives owner/repo from the PR URL when the entry name is empty", () => {
|
|
113
|
+
const wb = create(WorkspaceWriteBackSchema, {
|
|
114
|
+
workspaceEntryName: "",
|
|
115
|
+
pullRequestUrl: "https://github.com/acme/my-app/pull/42",
|
|
116
|
+
});
|
|
117
|
+
expect(writeBackDisplayName(wb)).toBe("acme/my-app");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("falls back to the generic label when neither name nor PR URL exists", () => {
|
|
121
|
+
const wb = create(WorkspaceWriteBackSchema, {
|
|
122
|
+
workspaceEntryName: "",
|
|
123
|
+
pullRequestUrl: "",
|
|
124
|
+
});
|
|
125
|
+
expect(writeBackDisplayName(wb)).toBe("Workspace");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("does not mis-parse a non-PR URL", () => {
|
|
129
|
+
const wb = create(WorkspaceWriteBackSchema, {
|
|
130
|
+
workspaceEntryName: "",
|
|
131
|
+
pullRequestUrl: "https://github.com/acme/my-app",
|
|
132
|
+
});
|
|
133
|
+
expect(writeBackDisplayName(wb)).toBe("Workspace");
|
|
134
|
+
});
|
|
135
|
+
});
|
package/src/execution/index.ts
CHANGED
|
@@ -80,6 +80,13 @@ export type { UseWorkspaceWriteBacksReturn } from "./useWorkspaceWriteBacks.js";
|
|
|
80
80
|
export { WriteBackCard } from "./WriteBackCard.js";
|
|
81
81
|
export type { WriteBackCardProps } from "./WriteBackCard.js";
|
|
82
82
|
|
|
83
|
+
export {
|
|
84
|
+
parseDiffStatSummary,
|
|
85
|
+
trailingDiffStatLine,
|
|
86
|
+
writeBackDisplayName,
|
|
87
|
+
} from "./write-back-utils.js";
|
|
88
|
+
export type { DiffStatSummary } from "./write-back-utils.js";
|
|
89
|
+
|
|
83
90
|
export { FileChangesView, FileChangeDiff } from "./FileChangesView.js";
|
|
84
91
|
export type { FileChangesViewProps, FileChangeDiffProps } from "./FileChangesView.js";
|
|
85
92
|
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { WorkspaceWriteBack } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/writeback_pb";
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// diff --stat summary parsing
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Aggregate change statistics parsed from a `git diff --stat` summary line.
|
|
9
|
+
*
|
|
10
|
+
* @see parseDiffStatSummary
|
|
11
|
+
*/
|
|
12
|
+
export interface DiffStatSummary {
|
|
13
|
+
/** Number of files with changes. */
|
|
14
|
+
readonly filesChanged: number;
|
|
15
|
+
/** Total inserted lines across all files. */
|
|
16
|
+
readonly insertions: number;
|
|
17
|
+
/** Total deleted lines across all files. */
|
|
18
|
+
readonly deletions: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The trailing summary line git appends to `--stat` output. All three count
|
|
23
|
+
* segments are optional-but-ordered in git's formatting; an insertions-only
|
|
24
|
+
* diff omits the deletions segment entirely (and vice versa).
|
|
25
|
+
*/
|
|
26
|
+
const DIFF_STAT_SUMMARY_RE =
|
|
27
|
+
/^(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?$/;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Parses the trailing summary line of a `git diff --stat` output into
|
|
31
|
+
* structured counts.
|
|
32
|
+
*
|
|
33
|
+
* `WorkspaceWriteBack.diff_summary` stores the raw `--stat` text (see the
|
|
34
|
+
* runner's `WriteBackCoordinator.updateStatus`). The per-file lines above the
|
|
35
|
+
* summary are NOT parseable honestly — git truncates long paths — but the
|
|
36
|
+
* trailing "N files changed, M insertions(+), K deletions(-)" line is stable
|
|
37
|
+
* and locale-independent, so it is the one part safe to structure.
|
|
38
|
+
*
|
|
39
|
+
* Returns `null` when the text has no recognizable summary line (empty
|
|
40
|
+
* string, or a format drift), letting callers fall back to rendering the raw
|
|
41
|
+
* text rather than showing wrong numbers.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* parseDiffStatSummary(" notes.md | 55 +++\n 1 file changed, 55 insertions(+)");
|
|
46
|
+
* // { filesChanged: 1, insertions: 55, deletions: 0 }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export function parseDiffStatSummary(
|
|
50
|
+
diffSummary: string,
|
|
51
|
+
): DiffStatSummary | null {
|
|
52
|
+
const line = trailingDiffStatLine(diffSummary);
|
|
53
|
+
if (line === null) return null;
|
|
54
|
+
|
|
55
|
+
const match = DIFF_STAT_SUMMARY_RE.exec(line);
|
|
56
|
+
if (!match) return null;
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
filesChanged: Number(match[1]),
|
|
60
|
+
insertions: Number(match[2] ?? 0),
|
|
61
|
+
deletions: Number(match[3] ?? 0),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The last non-empty line of a `diff --stat` text — the summary line when the
|
|
67
|
+
* text is well-formed, and the honest single-line fallback to display when
|
|
68
|
+
* {@link parseDiffStatSummary} cannot structure it. `null` for blank input.
|
|
69
|
+
*/
|
|
70
|
+
export function trailingDiffStatLine(diffSummary: string): string | null {
|
|
71
|
+
const lines = diffSummary.split("\n");
|
|
72
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
73
|
+
const line = lines[i].trim();
|
|
74
|
+
if (line) return line;
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Display name resolution
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
/** Matches `https://github.com/{owner}/{repo}/pull/{n}` (any git host). */
|
|
84
|
+
const PULL_REQUEST_URL_RE = /^https?:\/\/[^/]+\/([^/]+)\/([^/]+)\/pull\/\d+/;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Resolves the human-facing name for a write-back's header.
|
|
88
|
+
*
|
|
89
|
+
* A write-back names its workspace entry, but single-entry sessions can
|
|
90
|
+
* legitimately write back under an EMPTY `workspace_entry_name` — the runner's
|
|
91
|
+
* `WriteBackCoordinator.resolveEntry` convention, mirrored by
|
|
92
|
+
* `useWorkspaceReadRefs`. (The Console derives entry names from the git URL,
|
|
93
|
+
* so this mostly surfaces for CLI/SDK-created sessions.) Rather than render a
|
|
94
|
+
* blank title, fall back through what the record can still prove:
|
|
95
|
+
*
|
|
96
|
+
* 1. `workspace_entry_name` — the configured name, when present.
|
|
97
|
+
* 2. `owner/repo` parsed from `pull_request_url` — the repository identity.
|
|
98
|
+
* 3. `"Workspace"` — the honest generic label when neither exists.
|
|
99
|
+
*/
|
|
100
|
+
export function writeBackDisplayName(writeBack: WorkspaceWriteBack): string {
|
|
101
|
+
if (writeBack.workspaceEntryName) return writeBack.workspaceEntryName;
|
|
102
|
+
|
|
103
|
+
const match = PULL_REQUEST_URL_RE.exec(writeBack.pullRequestUrl);
|
|
104
|
+
if (match) return `${match[1]}/${match[2]}`;
|
|
105
|
+
|
|
106
|
+
return "Workspace";
|
|
107
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -323,6 +323,9 @@ export {
|
|
|
323
323
|
execIdFromStorageKey,
|
|
324
324
|
useWorkspaceWriteBacks,
|
|
325
325
|
WriteBackCard,
|
|
326
|
+
parseDiffStatSummary,
|
|
327
|
+
trailingDiffStatLine,
|
|
328
|
+
writeBackDisplayName,
|
|
326
329
|
FileChangesView,
|
|
327
330
|
FileChangeDiff,
|
|
328
331
|
EmptyChangeNotice,
|
|
@@ -419,6 +422,7 @@ export type {
|
|
|
419
422
|
UseFileChangeContentReturn,
|
|
420
423
|
UseWorkspaceWriteBacksReturn,
|
|
421
424
|
WriteBackCardProps,
|
|
425
|
+
DiffStatSummary,
|
|
422
426
|
FileChangesViewProps,
|
|
423
427
|
FileChangeDiffProps,
|
|
424
428
|
EmptyChangeNoticeProps,
|
|
@@ -980,6 +984,32 @@ export type {
|
|
|
980
984
|
InvitationRedemptionProps,
|
|
981
985
|
} from "./invitation/index.js";
|
|
982
986
|
|
|
987
|
+
// Sharing — shared-agent public profile, the anonymous-visitor chat organism,
|
|
988
|
+
// and the owner-side Share experience (dialog, kebab hook, sharing mutation).
|
|
989
|
+
export {
|
|
990
|
+
useSharedAgentProfile,
|
|
991
|
+
SharedAgentChat,
|
|
992
|
+
sharingAudienceFromProto,
|
|
993
|
+
useUpdateAgentSharing,
|
|
994
|
+
useRotateShareLink,
|
|
995
|
+
ShareAgentDialog,
|
|
996
|
+
useShareAgent,
|
|
997
|
+
validateOrigin,
|
|
998
|
+
MAX_ALLOWED_ORIGINS,
|
|
999
|
+
} from "./sharing/index.js";
|
|
1000
|
+
export type {
|
|
1001
|
+
UseSharedAgentProfileOptions,
|
|
1002
|
+
UseSharedAgentProfileReturn,
|
|
1003
|
+
SharedAgentChatProps,
|
|
1004
|
+
AgentSharingDraft,
|
|
1005
|
+
SharingAudience,
|
|
1006
|
+
UseUpdateAgentSharingReturn,
|
|
1007
|
+
UseRotateShareLinkReturn,
|
|
1008
|
+
ShareAgentDialogProps,
|
|
1009
|
+
UseShareAgentArgs,
|
|
1010
|
+
UseShareAgentReturn,
|
|
1011
|
+
} from "./sharing/index.js";
|
|
1012
|
+
|
|
983
1013
|
// Error — structured error display with classification, retry, and contextual guidance
|
|
984
1014
|
export { ErrorMessage, SecretFlowErrorGuide, isSecretFlowError } from "./error/index.js";
|
|
985
1015
|
export type { ErrorMessageProps, SecretFlowErrorGuideProps } from "./error/index.js";
|
|
@@ -1136,6 +1166,10 @@ export type {
|
|
|
1136
1166
|
export { Tabs } from "./tabs/index.js";
|
|
1137
1167
|
export type { TabsProps, TabItem } from "./tabs/index.js";
|
|
1138
1168
|
|
|
1169
|
+
// Switch — accessible on/off toggle primitive (WAI-ARIA Switch pattern)
|
|
1170
|
+
export { Switch } from "./switch/index.js";
|
|
1171
|
+
export type { SwitchProps } from "./switch/index.js";
|
|
1172
|
+
|
|
1139
1173
|
// Resource Detail — headless hooks, action bar, and composed shell for resource detail pages
|
|
1140
1174
|
export {
|
|
1141
1175
|
useCopyResource,
|
|
@@ -15,10 +15,14 @@ describe("useKeyStability", () => {
|
|
|
15
15
|
let warnSpy: ReturnType<typeof vi.spyOn>;
|
|
16
16
|
|
|
17
17
|
beforeEach(() => {
|
|
18
|
+
// Perf logging is opt-in (off by default). Enable it via the browser
|
|
19
|
+
// runtime flag so these behavioral assertions exercise the warning path.
|
|
20
|
+
(globalThis as { __STIGMER_PERF__?: boolean }).__STIGMER_PERF__ = true;
|
|
18
21
|
warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
19
22
|
});
|
|
20
23
|
|
|
21
24
|
afterEach(() => {
|
|
25
|
+
delete (globalThis as { __STIGMER_PERF__?: boolean }).__STIGMER_PERF__;
|
|
22
26
|
warnSpy.mockRestore();
|
|
23
27
|
});
|
|
24
28
|
|
|
@@ -6,10 +6,14 @@ describe("useRenderTracer", () => {
|
|
|
6
6
|
let debugSpy: ReturnType<typeof vi.spyOn>;
|
|
7
7
|
|
|
8
8
|
beforeEach(() => {
|
|
9
|
+
// Perf logging is opt-in (off by default). Enable it via the browser
|
|
10
|
+
// runtime flag so these behavioral assertions exercise the logging path.
|
|
11
|
+
(globalThis as { __STIGMER_PERF__?: boolean }).__STIGMER_PERF__ = true;
|
|
9
12
|
debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {});
|
|
10
13
|
});
|
|
11
14
|
|
|
12
15
|
afterEach(() => {
|
|
16
|
+
delete (globalThis as { __STIGMER_PERF__?: boolean }).__STIGMER_PERF__;
|
|
13
17
|
debugSpy.mockRestore();
|
|
14
18
|
});
|
|
15
19
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type RefObject, useEffect, useRef } from "react";
|
|
2
|
-
|
|
3
|
-
const DEV = process.env.NODE_ENV !== "production";
|
|
2
|
+
import { isPerfLoggingEnabled } from "./enabled.js";
|
|
4
3
|
|
|
5
4
|
/** Log the node count every Nth trigger. */
|
|
6
5
|
const LOG_EVERY = 10;
|
|
@@ -23,7 +22,7 @@ export function useDomNodeCount(
|
|
|
23
22
|
const triggerCountRef = useRef(0);
|
|
24
23
|
|
|
25
24
|
useEffect(() => {
|
|
26
|
-
if (!
|
|
25
|
+
if (!isPerfLoggingEnabled()) return;
|
|
27
26
|
|
|
28
27
|
triggerCountRef.current += 1;
|
|
29
28
|
if (triggerCountRef.current % LOG_EVERY !== 0) return;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Master switch for the SDK's dev-only performance instrumentation (the
|
|
2
|
+
// `[stgm:perf:*]` logs emitted by useStreamRate, useRenderTracer, useDomNodeCount,
|
|
3
|
+
// useKeyStability, and DevProfiler).
|
|
4
|
+
//
|
|
5
|
+
// Off by default in every environment. These logs are pure noise for anyone not
|
|
6
|
+
// actively profiling, and in a non-browser TTY consumer — notably the `stigmer`
|
|
7
|
+
// CLI's Ink UI — console output is not filtered by a devtools log level, so it
|
|
8
|
+
// corrupts the rendered terminal. The old `NODE_ENV !== "production"` gate
|
|
9
|
+
// assumed a browser devtools context (where `console.debug` is hidden by
|
|
10
|
+
// default), which does not hold for Node consumers.
|
|
11
|
+
//
|
|
12
|
+
// Opt in without a rebuild:
|
|
13
|
+
// - Node (CLI, tests): STIGMER_PERF=1 stigmer run ...
|
|
14
|
+
// - Browser (web/desktop devtools): globalThis.__STIGMER_PERF__ = true
|
|
15
|
+
//
|
|
16
|
+
// Still hard-gated on non-production so production bundles dead-code-eliminate
|
|
17
|
+
// the instrumentation entirely (bundlers inline `process.env.NODE_ENV`).
|
|
18
|
+
|
|
19
|
+
/** Reads the Node opt-in env var, guarding environments without `process`. */
|
|
20
|
+
function envFlagEnabled(): boolean {
|
|
21
|
+
const env = typeof process !== "undefined" ? process.env : undefined;
|
|
22
|
+
const value = env?.STIGMER_PERF;
|
|
23
|
+
return value === "1" || value === "true";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Reads the browser runtime opt-in (toggle live from devtools). */
|
|
27
|
+
function globalFlagEnabled(): boolean {
|
|
28
|
+
return (globalThis as { __STIGMER_PERF__?: unknown }).__STIGMER_PERF__ === true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Whether the SDK's dev-perf instrumentation may emit output. Evaluated per call
|
|
33
|
+
* (not cached) so a browser runtime toggle takes effect without a remount.
|
|
34
|
+
* Always `false` in production.
|
|
35
|
+
*/
|
|
36
|
+
export function isPerfLoggingEnabled(): boolean {
|
|
37
|
+
if (process.env.NODE_ENV === "production") return false;
|
|
38
|
+
return envFlagEnabled() || globalFlagEnabled();
|
|
39
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { Profiler, type ProfilerOnRenderCallback, type ReactNode } from "react";
|
|
4
|
-
|
|
5
|
-
const DEV = process.env.NODE_ENV !== "production";
|
|
4
|
+
import { isPerfLoggingEnabled } from "./enabled.js";
|
|
6
5
|
|
|
7
6
|
/** Log every Nth commit to avoid console flood during streaming. */
|
|
8
7
|
const LOG_EVERY = 10;
|
|
@@ -31,9 +30,9 @@ const onRender: ProfilerOnRenderCallback = (
|
|
|
31
30
|
* In dev mode, logs commit-level timing (`actualDuration`,
|
|
32
31
|
* `baseDuration`, mount vs update phase) with sampled output.
|
|
33
32
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* overhead
|
|
33
|
+
* Off by default in every environment (and always in production) — enable via
|
|
34
|
+
* {@link isPerfLoggingEnabled}'s opt-in flags. When disabled, children render
|
|
35
|
+
* with zero Profiler overhead.
|
|
37
36
|
*/
|
|
38
37
|
export function DevProfiler({
|
|
39
38
|
id,
|
|
@@ -42,7 +41,7 @@ export function DevProfiler({
|
|
|
42
41
|
readonly id: string;
|
|
43
42
|
readonly children: ReactNode;
|
|
44
43
|
}) {
|
|
45
|
-
if (!
|
|
44
|
+
if (!isPerfLoggingEnabled()) return children;
|
|
46
45
|
|
|
47
46
|
return (
|
|
48
47
|
<Profiler id={id} onRender={onRender}>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useRef } from "react";
|
|
2
|
-
|
|
3
|
-
const DEV = process.env.NODE_ENV !== "production";
|
|
2
|
+
import { isPerfLoggingEnabled } from "./enabled.js";
|
|
4
3
|
|
|
5
4
|
/** Minimal shape expected from a keyed thread item. */
|
|
6
5
|
interface KeyedItem {
|
|
@@ -25,7 +24,7 @@ interface KeyedItem {
|
|
|
25
24
|
export function useKeyStability(items: readonly KeyedItem[]): void {
|
|
26
25
|
const prevRef = useRef<readonly KeyedItem[] | null>(null);
|
|
27
26
|
|
|
28
|
-
if (!
|
|
27
|
+
if (!isPerfLoggingEnabled()) return;
|
|
29
28
|
|
|
30
29
|
// Detect duplicate keys within the current render.
|
|
31
30
|
const seen = new Map<string, number>();
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useRef } from "react";
|
|
2
|
-
|
|
3
|
-
const DEV = process.env.NODE_ENV !== "production";
|
|
2
|
+
import { isPerfLoggingEnabled } from "./enabled.js";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Sampling interval: log every Nth render to avoid flooding the
|
|
@@ -12,8 +11,8 @@ const LOG_EVERY = 10;
|
|
|
12
11
|
* Dev-only hook that tracks render count and reports which props
|
|
13
12
|
* changed (by shallow referential equality) since the last render.
|
|
14
13
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* Off by default in every environment (and always in production) — enable via
|
|
15
|
+
* {@link isPerfLoggingEnabled}'s opt-in flags.
|
|
17
16
|
*
|
|
18
17
|
* @param componentName - Stable label for console output.
|
|
19
18
|
* @param props - Key/value map of props to track. Pass only the props
|
|
@@ -26,7 +25,7 @@ export function useRenderTracer(
|
|
|
26
25
|
const countRef = useRef(0);
|
|
27
26
|
const prevRef = useRef<Record<string, unknown> | null>(null);
|
|
28
27
|
|
|
29
|
-
if (!
|
|
28
|
+
if (!isPerfLoggingEnabled()) return;
|
|
30
29
|
|
|
31
30
|
countRef.current += 1;
|
|
32
31
|
const count = countRef.current;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useRef } from "react";
|
|
2
|
-
|
|
3
|
-
const DEV = process.env.NODE_ENV !== "production";
|
|
2
|
+
import { isPerfLoggingEnabled } from "./enabled.js";
|
|
4
3
|
|
|
5
4
|
/** Rolling window size for interval statistics. */
|
|
6
5
|
const WINDOW_SIZE = 30;
|
|
@@ -42,12 +41,13 @@ const NOOP_TRACKER: StreamRateTracker = {
|
|
|
42
41
|
* loop (not during render), so it uses a ref-backed mutable object
|
|
43
42
|
* rather than React state.
|
|
44
43
|
*
|
|
45
|
-
*
|
|
44
|
+
* Returns a no-op tracker unless perf logging is explicitly enabled
|
|
45
|
+
* (see {@link isPerfLoggingEnabled}) — off by default in every environment.
|
|
46
46
|
*/
|
|
47
47
|
export function useStreamRate(): StreamRateTracker {
|
|
48
48
|
const stateRef = useRef<StreamRateState | null>(null);
|
|
49
49
|
|
|
50
|
-
if (!
|
|
50
|
+
if (!isPerfLoggingEnabled()) return NOOP_TRACKER;
|
|
51
51
|
|
|
52
52
|
if (!stateRef.current) {
|
|
53
53
|
stateRef.current = {
|
|
@@ -8,6 +8,7 @@ import { useSsoProvider } from "../identity-provider/useSsoProvider.js";
|
|
|
8
8
|
import { VisibilityBadge, VisibilitySelector } from "./VisibilitySelector.js";
|
|
9
9
|
import {
|
|
10
10
|
blueprintVisibilityLevels,
|
|
11
|
+
environmentVisibilityLevels,
|
|
11
12
|
INSTANCE_VISIBILITY_LEVELS,
|
|
12
13
|
} from "./visibilityLevels.js";
|
|
13
14
|
import {
|
|
@@ -28,6 +29,7 @@ const FGA_KIND: Record<VisibilityResourceKind, string> = {
|
|
|
28
29
|
mcpServer: "mcp_server",
|
|
29
30
|
agentInstance: "agent_instance",
|
|
30
31
|
workflowInstance: "workflow_instance",
|
|
32
|
+
environment: "environment",
|
|
31
33
|
};
|
|
32
34
|
|
|
33
35
|
const INSTANCE_KINDS: ReadonlySet<VisibilityResourceKind> = new Set([
|
|
@@ -79,6 +81,9 @@ export interface ResourceVisibilityControlProps {
|
|
|
79
81
|
* set collapses to Private / Public.
|
|
80
82
|
* - Instances: Private / Organization / Public — platform is excluded by
|
|
81
83
|
* design to preserve tenant isolation.
|
|
84
|
+
* - Environments: Private / Organization only — secret values never leave
|
|
85
|
+
* the org boundary. In `local` mode there are no levels to choose (the
|
|
86
|
+
* OSS backend is single-user), so the control degrades to a badge.
|
|
82
87
|
*
|
|
83
88
|
* The backend remains the enforcer (`ValidateVisibilityStep` rejects
|
|
84
89
|
* platform without an IdP); the gate here only prevents offering an option
|
|
@@ -96,18 +101,23 @@ export function ResourceVisibilityControl({
|
|
|
96
101
|
const deploymentMode = useDeploymentMode();
|
|
97
102
|
|
|
98
103
|
const isInstance = INSTANCE_KINDS.has(kind);
|
|
104
|
+
const isEnvironment = kind === "environment";
|
|
99
105
|
// The IdP lookup only matters for blueprints in cloud mode; passing null
|
|
100
106
|
// makes the hook a stable no-op everywhere else.
|
|
101
107
|
const idpLookupOrg =
|
|
102
|
-
!isInstance && deploymentMode === "cloud"
|
|
108
|
+
!isInstance && !isEnvironment && deploymentMode === "cloud"
|
|
109
|
+
? (org ?? null)
|
|
110
|
+
: null;
|
|
103
111
|
const { ssoProvider } = useSsoProvider(idpLookupOrg);
|
|
104
112
|
|
|
105
|
-
const options =
|
|
106
|
-
?
|
|
107
|
-
:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
const options = isEnvironment
|
|
114
|
+
? environmentVisibilityLevels(deploymentMode)
|
|
115
|
+
: isInstance
|
|
116
|
+
? INSTANCE_VISIBILITY_LEVELS
|
|
117
|
+
: blueprintVisibilityLevels({
|
|
118
|
+
deploymentMode,
|
|
119
|
+
hasIdentityProvider: ssoProvider !== null,
|
|
120
|
+
});
|
|
111
121
|
|
|
112
122
|
const handleChange = useCallback(
|
|
113
123
|
async (next: ApiResourceVisibility) => {
|
|
@@ -125,6 +135,12 @@ export function ResourceVisibilityControl({
|
|
|
125
135
|
|
|
126
136
|
const badge = <VisibilityBadge visibility={visibility} className={className} />;
|
|
127
137
|
|
|
138
|
+
// Fewer than two levels means there is nothing to choose (e.g. an
|
|
139
|
+
// environment in local mode) — stay legible with the read-only badge.
|
|
140
|
+
if (options.length < 2) {
|
|
141
|
+
return badge;
|
|
142
|
+
}
|
|
143
|
+
|
|
128
144
|
return (
|
|
129
145
|
<PermissionGate
|
|
130
146
|
resource={{ kind: FGA_KIND[kind], id: resourceId }}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
3
|
+
import { environmentVisibilityLevels } from "../visibilityLevels";
|
|
4
|
+
|
|
5
|
+
describe("environmentVisibilityLevels", () => {
|
|
6
|
+
it("offers exactly Private and Organization in cloud mode", () => {
|
|
7
|
+
const levels = environmentVisibilityLevels("cloud");
|
|
8
|
+
expect(levels.map((l) => l.value)).toEqual([
|
|
9
|
+
ApiResourceVisibility.visibility_private,
|
|
10
|
+
ApiResourceVisibility.visibility_org,
|
|
11
|
+
]);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("never offers public or platform — secrets stay inside the org", () => {
|
|
15
|
+
for (const mode of ["cloud", "local"] as const) {
|
|
16
|
+
const values = environmentVisibilityLevels(mode).map((l) => l.value);
|
|
17
|
+
expect(values).not.toContain(ApiResourceVisibility.visibility_public);
|
|
18
|
+
expect(values).not.toContain(ApiResourceVisibility.visibility_platform);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("confirms before escalating to org (credentials become runtime-usable org-wide)", () => {
|
|
23
|
+
const org = environmentVisibilityLevels("cloud").find(
|
|
24
|
+
(l) => l.value === ApiResourceVisibility.visibility_org,
|
|
25
|
+
);
|
|
26
|
+
expect(org?.confirmPrompt).toBeTruthy();
|
|
27
|
+
expect(org?.description).toContain("secret values stay hidden");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("collapses to a single read-only level in local mode", () => {
|
|
31
|
+
expect(environmentVisibilityLevels("local")).toHaveLength(1);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -14,7 +14,8 @@ export type VisibilityResourceKind =
|
|
|
14
14
|
| "mcpServer"
|
|
15
15
|
| "workflow"
|
|
16
16
|
| "agentInstance"
|
|
17
|
-
| "workflowInstance"
|
|
17
|
+
| "workflowInstance"
|
|
18
|
+
| "environment";
|
|
18
19
|
|
|
19
20
|
/** Return value of {@link useUpdateVisibility}. */
|
|
20
21
|
export interface UseUpdateVisibilityReturn {
|
|
@@ -35,8 +36,10 @@ export interface UseUpdateVisibilityReturn {
|
|
|
35
36
|
* Behavior hook that updates the visibility of a resource.
|
|
36
37
|
*
|
|
37
38
|
* Supports blueprints (Agent, Workflow, Skill, MCP Server) with the
|
|
38
|
-
* full private/org/public/platform spectrum,
|
|
39
|
-
* (AgentInstance, WorkflowInstance) with private/org/public
|
|
39
|
+
* full private/org/public/platform spectrum, instances
|
|
40
|
+
* (AgentInstance, WorkflowInstance) with private/org/public, and
|
|
41
|
+
* environments with private/org (secret values never leave the org
|
|
42
|
+
* boundary, so broader levels are rejected by the backend).
|
|
40
43
|
*
|
|
41
44
|
* Wraps the generated `stigmer.{kind}.updateVisibility()` SDK method
|
|
42
45
|
* with loading and error state management. The hook is stateless with
|
|
@@ -99,6 +102,9 @@ export function useUpdateVisibility(
|
|
|
99
102
|
case "workflowInstance":
|
|
100
103
|
await stigmer.workflowInstance.updateVisibility(input);
|
|
101
104
|
break;
|
|
105
|
+
case "environment":
|
|
106
|
+
await stigmer.environment.updateVisibility(input);
|
|
107
|
+
break;
|
|
102
108
|
}
|
|
103
109
|
} catch (err) {
|
|
104
110
|
setError(toError(err));
|