@stigmer/cli 3.23.0 → 3.24.0
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/commands/bootstrap.d.ts.map +1 -1
- package/commands/bootstrap.js +16 -57
- package/commands/bootstrap.js.map +1 -1
- package/commands/config/context.d.ts.map +1 -1
- package/commands/config/context.js +41 -5
- package/commands/config/context.js.map +1 -1
- package/commands/install.js +1 -1
- package/commands/install.js.map +1 -1
- package/commands/push.js +1 -1
- package/commands/push.js.map +1 -1
- package/commands/search.d.ts.map +1 -1
- package/commands/search.js +0 -2
- package/commands/search.js.map +1 -1
- package/commands/up.js +1 -1
- package/commands/up.js.map +1 -1
- package/config/index.d.ts +1 -1
- package/config/index.d.ts.map +1 -1
- package/config/index.js +1 -1
- package/config/index.js.map +1 -1
- package/config/resolve.d.ts +8 -0
- package/config/resolve.d.ts.map +1 -1
- package/config/resolve.js +8 -8
- package/config/resolve.js.map +1 -1
- package/local/bootstrap.d.ts +9 -29
- package/local/bootstrap.d.ts.map +1 -1
- package/local/bootstrap.js +61 -69
- package/local/bootstrap.js.map +1 -1
- package/local/daemon/launch.d.ts +2 -2
- package/local/daemon/launch.d.ts.map +1 -1
- package/marketplace/official.d.ts.map +1 -1
- package/marketplace/official.js +6 -5
- package/marketplace/official.js.map +1 -1
- package/marketplace/render.d.ts.map +1 -1
- package/marketplace/render.js +0 -3
- package/marketplace/render.js.map +1 -1
- package/package.json +7 -7
- package/resources/search.d.ts +1 -3
- package/resources/search.d.ts.map +1 -1
- package/resources/search.js +0 -1
- package/resources/search.js.map +1 -1
- package/resources/share.d.ts.map +1 -1
- package/resources/share.js +20 -24
- package/resources/share.js.map +1 -1
- package/resources/skill.d.ts +2 -2
- package/resources/skill.d.ts.map +1 -1
- package/resources/skill.js +19 -10
- package/resources/skill.js.map +1 -1
- package/src/commands/bootstrap.test.ts +19 -75
- package/src/commands/bootstrap.ts +19 -68
- package/src/commands/config/context.test.ts +171 -0
- package/src/commands/config/context.ts +50 -5
- package/src/commands/install.ts +1 -1
- package/src/commands/marketplace.test.ts +2 -2
- package/src/commands/push.ts +1 -1
- package/src/commands/search.ts +0 -3
- package/src/commands/up.ts +1 -1
- package/src/config/index.ts +1 -0
- package/src/config/resolve.test.ts +2 -2
- package/src/config/resolve.ts +8 -8
- package/src/local/bootstrap.test.ts +132 -65
- package/src/local/bootstrap.ts +64 -139
- package/src/local/daemon/launch.ts +2 -2
- package/src/marketplace/official.ts +6 -5
- package/src/marketplace/read.test.ts +2 -3
- package/src/marketplace/render.ts +0 -3
- package/src/resources/apply/apply.test.ts +10 -10
- package/src/resources/read-completion.integration.test.ts +0 -2
- package/src/resources/search.ts +1 -4
- package/src/resources/share.test.ts +7 -60
- package/src/resources/share.ts +22 -27
- package/src/resources/skill.test.ts +20 -13
- package/src/resources/skill.ts +25 -14
- package/local/plugins/defaults.d.ts +0 -55
- package/local/plugins/defaults.d.ts.map +0 -1
- package/local/plugins/defaults.js +0 -111
- package/local/plugins/defaults.js.map +0 -1
- package/local/system-org.d.ts +0 -15
- package/local/system-org.d.ts.map +0 -1
- package/local/system-org.js +0 -57
- package/local/system-org.js.map +0 -1
- package/src/local/plugins/defaults.test.ts +0 -271
- package/src/local/plugins/defaults.ts +0 -179
- package/src/local/system-org.test.ts +0 -124
- package/src/local/system-org.ts +0 -63
|
@@ -51,20 +51,20 @@ function handlerWith(opts: HandlerOptions): { handler: ApplyHandler; calls: Upda
|
|
|
51
51
|
|
|
52
52
|
describe("applyMessage declared-visibility follow-up", () => {
|
|
53
53
|
it("lands a declared level the update preserved away, and reflects it on the outcome", async () => {
|
|
54
|
-
// Server preserved stored org; manifest declares
|
|
54
|
+
// Server preserved stored org; manifest declares platform.
|
|
55
55
|
const { handler, calls } = handlerWith({
|
|
56
56
|
applyReturns: agent(ApiResourceVisibility.visibility_org),
|
|
57
|
-
updateVisibility: () => Promise.resolve(agent(ApiResourceVisibility.
|
|
57
|
+
updateVisibility: () => Promise.resolve(agent(ApiResourceVisibility.visibility_platform)),
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
const outcome = await applyMessage(controller, handler, agent(ApiResourceVisibility.
|
|
60
|
+
const outcome = await applyMessage(controller, handler, agent(ApiResourceVisibility.visibility_platform), "acme", false);
|
|
61
61
|
|
|
62
62
|
expect(calls).toHaveLength(1);
|
|
63
63
|
expect(calls[0].resourceId).toBe("agent-1");
|
|
64
|
-
expect(calls[0].visibility).toBe(ApiResourceVisibility.
|
|
64
|
+
expect(calls[0].visibility).toBe(ApiResourceVisibility.visibility_platform);
|
|
65
65
|
expect(outcome.warning).toBeUndefined();
|
|
66
66
|
const appliedMeta = (outcome.applied as { metadata?: { visibility?: ApiResourceVisibility } })?.metadata;
|
|
67
|
-
expect(appliedMeta?.visibility).toBe(ApiResourceVisibility.
|
|
67
|
+
expect(appliedMeta?.visibility).toBe(ApiResourceVisibility.visibility_platform);
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
it("skips the follow-up when the manifest omits visibility", async () => {
|
|
@@ -87,11 +87,11 @@ describe("applyMessage declared-visibility follow-up", () => {
|
|
|
87
87
|
|
|
88
88
|
it("skips the follow-up when the server already matches (idempotent re-apply)", async () => {
|
|
89
89
|
const { handler, calls } = handlerWith({
|
|
90
|
-
applyReturns: agent(ApiResourceVisibility.
|
|
90
|
+
applyReturns: agent(ApiResourceVisibility.visibility_platform),
|
|
91
91
|
updateVisibility: () => Promise.reject(new Error("must not be called")),
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
-
const outcome = await applyMessage(controller, handler, agent(ApiResourceVisibility.
|
|
94
|
+
const outcome = await applyMessage(controller, handler, agent(ApiResourceVisibility.visibility_platform), "acme", false);
|
|
95
95
|
|
|
96
96
|
expect(calls).toHaveLength(0);
|
|
97
97
|
expect(outcome.warning).toBeUndefined();
|
|
@@ -102,7 +102,7 @@ describe("applyMessage declared-visibility follow-up", () => {
|
|
|
102
102
|
applyReturns: agent(ApiResourceVisibility.visibility_private),
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
const outcome = await applyMessage(controller, handler, agent(ApiResourceVisibility.
|
|
105
|
+
const outcome = await applyMessage(controller, handler, agent(ApiResourceVisibility.visibility_platform), "acme", false);
|
|
106
106
|
|
|
107
107
|
expect(outcome.warning).toMatch(/visibility cannot be changed declaratively/);
|
|
108
108
|
expect(outcome.warning).toMatch(/stored value is kept/);
|
|
@@ -116,7 +116,7 @@ describe("applyMessage declared-visibility follow-up", () => {
|
|
|
116
116
|
});
|
|
117
117
|
|
|
118
118
|
await expect(
|
|
119
|
-
applyMessage(controller, handler, agent(ApiResourceVisibility.
|
|
119
|
+
applyMessage(controller, handler, agent(ApiResourceVisibility.visibility_platform), "acme", false),
|
|
120
120
|
).rejects.toThrow(/spec applied, but the manifest's visibility change was rejected/);
|
|
121
121
|
});
|
|
122
122
|
|
|
@@ -126,7 +126,7 @@ describe("applyMessage declared-visibility follow-up", () => {
|
|
|
126
126
|
updateVisibility: () => Promise.reject(new Error("must not be called")),
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
-
const outcome = await applyMessage(controller, handler, agent(ApiResourceVisibility.
|
|
129
|
+
const outcome = await applyMessage(controller, handler, agent(ApiResourceVisibility.visibility_platform), "acme", true);
|
|
130
130
|
|
|
131
131
|
expect(calls).toHaveLength(0);
|
|
132
132
|
expect(outcome.applied).toBeUndefined();
|
|
@@ -100,7 +100,6 @@ describe("search integration", () => {
|
|
|
100
100
|
it("queries the SearchService and renders entries as protojson", async () => {
|
|
101
101
|
const outcome = await searchResources(client, ApiResourceKind.workflow, "deploy", {
|
|
102
102
|
org: "acme",
|
|
103
|
-
excludePublic: false,
|
|
104
103
|
page: 1,
|
|
105
104
|
pageSize: 20,
|
|
106
105
|
}, "json");
|
|
@@ -113,7 +112,6 @@ describe("search integration", () => {
|
|
|
113
112
|
it("renders a human table for search results", async () => {
|
|
114
113
|
const outcome = await searchResources(client, ApiResourceKind.workflow, "deploy", {
|
|
115
114
|
org: "acme",
|
|
116
|
-
excludePublic: false,
|
|
117
115
|
page: 1,
|
|
118
116
|
pageSize: 20,
|
|
119
117
|
}, "table");
|
package/src/resources/search.ts
CHANGED
|
@@ -11,10 +11,8 @@ import { SEARCH_TABLE } from "./list.js";
|
|
|
11
11
|
import { renderCollection } from "./render.js";
|
|
12
12
|
|
|
13
13
|
export interface SearchParams {
|
|
14
|
-
/** Organization scope. Empty searches across
|
|
14
|
+
/** Organization scope. Empty searches across every org the caller can access. */
|
|
15
15
|
readonly org: string;
|
|
16
|
-
/** Exclude public/platform resources, restricting to the caller's own. */
|
|
17
|
-
readonly excludePublic: boolean;
|
|
18
16
|
/** 1-indexed page number. */
|
|
19
17
|
readonly page: number;
|
|
20
18
|
/** Results per page. */
|
|
@@ -40,7 +38,6 @@ export async function searchResources(
|
|
|
40
38
|
kinds: [kind],
|
|
41
39
|
query,
|
|
42
40
|
org: params.org,
|
|
43
|
-
excludePublic: params.excludePublic,
|
|
44
41
|
page: { num: params.page, size: params.pageSize },
|
|
45
42
|
});
|
|
46
43
|
|
|
@@ -472,77 +472,24 @@ describe("shareAgent --reset-link (rotatable share token)", () => {
|
|
|
472
472
|
});
|
|
473
473
|
});
|
|
474
474
|
|
|
475
|
-
describe("shareAgent
|
|
476
|
-
it("
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
const result = await shareAgent(client, "acme/support-agent", "consumer-org", {
|
|
480
|
-
enabled: true,
|
|
481
|
-
...CLOUD,
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
expect(applies).toHaveLength(1);
|
|
485
|
-
// The share is the caller org's channel: its URL, billing, and
|
|
486
|
-
// credentials — while the blueprint reference stays the provider's.
|
|
487
|
-
expect(applies[0].org).toBe("consumer-org");
|
|
488
|
-
expect(applies[0].slug).toBe("support-agent");
|
|
489
|
-
expect(applies[0].agentRef).toEqual({ org: "acme", slug: "support-agent" });
|
|
490
|
-
|
|
491
|
-
const link = result.sections.find((s) => s.title === "Public chat link");
|
|
492
|
-
expect(link?.items).toEqual(["https://app.stigmer.ai/chat/consumer-org/support-agent"]);
|
|
493
|
-
expect(result.hints.some((h) => h.includes("consumer-org's credits"))).toBe(true);
|
|
494
|
-
});
|
|
495
|
-
|
|
496
|
-
it("never edits the provider org's own share (canonical resolution is org-scoped)", async () => {
|
|
497
|
-
// The provider already shares this agent with its own config; the
|
|
498
|
-
// caller's toggle must create the CALLER org's share, not flip (or
|
|
499
|
-
// inherit the config of) the provider's row.
|
|
500
|
-
const providerShare = makeShare({
|
|
501
|
-
enabled: true,
|
|
502
|
-
allowedOrigins: ["https://provider.example.com"],
|
|
503
|
-
});
|
|
504
|
-
const { client, applies } = fakeClient(makeAgent(), providerShare);
|
|
505
|
-
|
|
506
|
-
await shareAgent(client, "acme/support-agent", "consumer-org", {
|
|
507
|
-
enabled: true,
|
|
508
|
-
...CLOUD,
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
expect(applies).toHaveLength(1);
|
|
512
|
-
expect(applies[0].org).toBe("consumer-org");
|
|
513
|
-
// Fresh channel, fresh config: the provider's origins must not leak
|
|
514
|
-
// into the caller org's share.
|
|
515
|
-
expect(applies[0].allowedOrigins).toEqual([]);
|
|
516
|
-
});
|
|
517
|
-
|
|
518
|
-
it("refuses --audience org with guidance (cross-org shares are public only)", async () => {
|
|
475
|
+
describe("shareAgent from another organization's context", () => {
|
|
476
|
+
it("refuses before any write, naming where the share lives and the plugin remedy", async () => {
|
|
477
|
+
// The server would refuse the agent_ref too; the CLI refuses first so
|
|
478
|
+
// the caller reads the remedy rather than a bare FAILED_PRECONDITION.
|
|
519
479
|
const { client, applies } = fakeClient(makeAgent(), null);
|
|
520
480
|
|
|
521
481
|
const err = await shareAgent(client, "acme/support-agent", "consumer-org", {
|
|
522
482
|
enabled: true,
|
|
523
|
-
audience: "org",
|
|
524
483
|
...CLOUD,
|
|
525
484
|
}).catch((e: unknown) => e);
|
|
526
485
|
|
|
527
486
|
expect(err).toBeInstanceOf(UsageError);
|
|
528
|
-
expect((err as Error).message).toContain("
|
|
487
|
+
expect((err as Error).message).toContain("lives in acme, not consumer-org");
|
|
488
|
+
expect((err as Error).message).toContain("install the plugin that carries it");
|
|
489
|
+
expect((err as Error).message).toContain("--org acme");
|
|
529
490
|
expect(classify(err)?.exitCode).toBe(ExitCode.Usage);
|
|
530
491
|
expect(applies).toHaveLength(0);
|
|
531
492
|
});
|
|
532
|
-
|
|
533
|
-
it("passes the server's fail-loud dependency refusal through unchanged", async () => {
|
|
534
|
-
// The D5 sweep names every non-public dependency; the CLI must
|
|
535
|
-
// surface that message verbatim — it tells the caller exactly what
|
|
536
|
-
// to ask the provider org to publish.
|
|
537
|
-
const refusal = new Error(
|
|
538
|
-
"cannot share acme/support-agent across organizations: it references resources that are not public: skill acme/private-skill",
|
|
539
|
-
);
|
|
540
|
-
const { client } = fakeClient(makeAgent(), null, { failWith: refusal });
|
|
541
|
-
|
|
542
|
-
await expect(
|
|
543
|
-
shareAgent(client, "acme/support-agent", "consumer-org", { enabled: true, ...CLOUD }),
|
|
544
|
-
).rejects.toThrow(/skill acme\/private-skill/);
|
|
545
|
-
});
|
|
546
493
|
});
|
|
547
494
|
|
|
548
495
|
describe("shareAgent errors", () => {
|
package/src/resources/share.ts
CHANGED
|
@@ -94,32 +94,28 @@ export async function shareAgent(
|
|
|
94
94
|
|
|
95
95
|
const agent = await resolveAgentRef(client, ref, org);
|
|
96
96
|
const agentOrg = agent.metadata?.org ?? "";
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
97
|
+
// A share lives in its agent's organization: its URL, billing and
|
|
98
|
+
// credential bindings belong to the organization that owns the agent.
|
|
99
|
+
// The server refuses an agent_ref in any other organization; refusing
|
|
100
|
+
// here names the remedy instead of surfacing a bare FAILED_PRECONDITION,
|
|
101
|
+
// and mirrors the share dialog, which never offers another org's agent.
|
|
102
|
+
// An empty org (an ID ref without context) is the agent's own.
|
|
103
|
+
if (org !== "" && org !== agentOrg) {
|
|
104
|
+
throw new UsageError(
|
|
105
|
+
`a share of ${agentOrg}/${agent.metadata?.slug ?? ""} lives in ${agentOrg}, not ${org}\n\n` +
|
|
106
|
+
"A share is the agent's own organization's channel. To share another\n" +
|
|
107
|
+
"organization's agent from yours, install the plugin that carries it and\n" +
|
|
108
|
+
"share the installed copy. To manage this agent's own share:\n" +
|
|
109
|
+
` stigmer share agent ${ref} --org ${agentOrg}`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
const shareOrg = agentOrg;
|
|
104
113
|
let share = await resolveCanonicalShare(client, agent, shareOrg);
|
|
105
114
|
const current = share?.spec;
|
|
106
115
|
|
|
107
116
|
const currentAudience = audienceFromProto(current?.audience);
|
|
108
117
|
const targetAudience = options.audience ?? currentAudience;
|
|
109
118
|
|
|
110
|
-
// Cross-org shares are public-audience only (decision 013 D3). The
|
|
111
|
-
// server refuses this too; refusing here names the remedy instead of
|
|
112
|
-
// surfacing a bare FAILED_PRECONDITION — and mirrors the share dialog,
|
|
113
|
-
// which hides the audience selector in cross-org mode.
|
|
114
|
-
if (isCrossOrg && targetAudience === "org") {
|
|
115
|
-
throw new UsageError(
|
|
116
|
-
"--audience org is not available for another organization's agent\n\n" +
|
|
117
|
-
`A share of ${agentOrg}/${agent.metadata?.slug ?? ""} in your organization\n` +
|
|
118
|
-
"(" + shareOrg + ") serves anyone with the link. Org-members-only sharing\n" +
|
|
119
|
-
"is limited to the agent's own organization.",
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
119
|
// Resetting the link is meaningless for org-members-only shares: their
|
|
124
120
|
// access is gated by live membership, and the member link never carries
|
|
125
121
|
// the token. Refuse rather than silently rotating an unused secret —
|
|
@@ -179,10 +175,10 @@ export async function shareAgent(
|
|
|
179
175
|
* slug equals the agent's (the server's default on create), else the
|
|
180
176
|
* first entry in that org, else null when the agent has never been shared
|
|
181
177
|
* there. Mirrors the web dialog's selection so both surfaces manage the
|
|
182
|
-
* same row. The org scope is
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
* the
|
|
178
|
+
* same row. The org scope is the agent's organization, where every share
|
|
179
|
+
* of it lives; the server applies the scope via the request's org field,
|
|
180
|
+
* so a share written in another organization before sharing across
|
|
181
|
+
* organizations was retired is never the row this command edits.
|
|
186
182
|
*/
|
|
187
183
|
async function resolveCanonicalShare(
|
|
188
184
|
client: Stigmer,
|
|
@@ -214,9 +210,8 @@ function audienceFromProto(audience: AgentShareAudience | undefined): ShareAudie
|
|
|
214
210
|
// was never shared before). Identity comes from the existing share when one
|
|
215
211
|
// exists — a manifest-created share may carry a non-default slug, and
|
|
216
212
|
// applying with the agent's slug would create a SECOND share — and from the
|
|
217
|
-
//
|
|
218
|
-
// made explicit
|
|
219
|
-
// agent's — decision 013). The audience is written explicitly — never left
|
|
213
|
+
// agent's org + the agent's slug otherwise (the server's own D2 default,
|
|
214
|
+
// made explicit). The audience is written explicitly — never left
|
|
220
215
|
// unspecified — so a console-managed org share can't drift back to public.
|
|
221
216
|
function preservingShareInput(
|
|
222
217
|
agent: Agent,
|
|
@@ -71,10 +71,10 @@ describe("parseSkillMetadata", () => {
|
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
it("parses a declared visibility from frontmatter", () => {
|
|
74
|
-
writeFileSync(join(dir, "SKILL.md"), "---\nname: my-skill\nvisibility:
|
|
74
|
+
writeFileSync(join(dir, "SKILL.md"), "---\nname: my-skill\nvisibility: org\n---\n");
|
|
75
75
|
expect(parseSkillMetadata(dir)).toEqual({
|
|
76
76
|
name: "my-skill",
|
|
77
|
-
visibility: ApiResourceVisibility.
|
|
77
|
+
visibility: ApiResourceVisibility.visibility_org,
|
|
78
78
|
});
|
|
79
79
|
});
|
|
80
80
|
|
|
@@ -85,16 +85,23 @@ describe("parseSkillMetadata", () => {
|
|
|
85
85
|
});
|
|
86
86
|
|
|
87
87
|
describe("parseVisibility", () => {
|
|
88
|
-
it("maps the
|
|
88
|
+
it("maps the three short forms", () => {
|
|
89
89
|
expect(parseVisibility("private")).toBe(ApiResourceVisibility.visibility_private);
|
|
90
|
-
expect(parseVisibility("public")).toBe(ApiResourceVisibility.visibility_public);
|
|
91
90
|
expect(parseVisibility("org")).toBe(ApiResourceVisibility.visibility_org);
|
|
92
91
|
expect(parseVisibility("platform")).toBe(ApiResourceVisibility.visibility_platform);
|
|
93
92
|
});
|
|
94
93
|
|
|
95
94
|
it("accepts canonical enum names and is case/whitespace insensitive", () => {
|
|
96
|
-
expect(parseVisibility("
|
|
97
|
-
expect(parseVisibility("
|
|
95
|
+
expect(parseVisibility(" Visibility_Platform ")).toBe(ApiResourceVisibility.visibility_platform);
|
|
96
|
+
expect(parseVisibility("ORG")).toBe(ApiResourceVisibility.visibility_org);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("refuses the retired public level by name, with the remedy and the valid values", () => {
|
|
100
|
+
for (const spelling of ["public", "visibility_public", " PUBLIC "]) {
|
|
101
|
+
expect(() => parseVisibility(spelling, "--visibility")).toThrow(
|
|
102
|
+
/invalid 'visibility' value '.*' in --visibility: the public level is retired[\s\S]*plugins[\s\S]*Valid values: private, org, platform\./,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
98
105
|
});
|
|
99
106
|
|
|
100
107
|
it("treats omitted/unspecified as not declared (undefined)", () => {
|
|
@@ -141,16 +148,16 @@ const NO_IGNORE = { respectGitignore: true, extraIgnore: [], extraInclude: [] };
|
|
|
141
148
|
|
|
142
149
|
describe("pushSkill visibility propagation", () => {
|
|
143
150
|
it("issues an UpdateVisibility RPC when the SKILL.md declares a non-matching visibility", async () => {
|
|
144
|
-
writeFileSync(join(dir, "SKILL.md"), "---\nname: my-skill\nvisibility:
|
|
151
|
+
writeFileSync(join(dir, "SKILL.md"), "---\nname: my-skill\nvisibility: org\n---\n");
|
|
145
152
|
const { client, calls } = fakeClient({ id: "skill-123", visibility: ApiResourceVisibility.visibility_private });
|
|
146
153
|
|
|
147
154
|
const result = await pushSkill(client, dir, "stigmer", "latest", "", NO_IGNORE);
|
|
148
155
|
|
|
149
156
|
expect(calls.push).toBe(1);
|
|
150
157
|
expect(calls.updateVisibility).toEqual([
|
|
151
|
-
{ resourceId: "skill-123", visibility: ApiResourceVisibility.
|
|
158
|
+
{ resourceId: "skill-123", visibility: ApiResourceVisibility.visibility_org },
|
|
152
159
|
]);
|
|
153
|
-
expect(result.visibility).toBe(ApiResourceVisibility.
|
|
160
|
+
expect(result.visibility).toBe(ApiResourceVisibility.visibility_org);
|
|
154
161
|
});
|
|
155
162
|
|
|
156
163
|
it("does not touch visibility when the SKILL.md omits it", async () => {
|
|
@@ -163,8 +170,8 @@ describe("pushSkill visibility propagation", () => {
|
|
|
163
170
|
});
|
|
164
171
|
|
|
165
172
|
it("skips the RPC when the server already matches the declared visibility", async () => {
|
|
166
|
-
writeFileSync(join(dir, "SKILL.md"), "---\nname: my-skill\nvisibility:
|
|
167
|
-
const { client, calls } = fakeClient({ id: "skill-123", visibility: ApiResourceVisibility.
|
|
173
|
+
writeFileSync(join(dir, "SKILL.md"), "---\nname: my-skill\nvisibility: org\n---\n");
|
|
174
|
+
const { client, calls } = fakeClient({ id: "skill-123", visibility: ApiResourceVisibility.visibility_org });
|
|
168
175
|
|
|
169
176
|
await pushSkill(client, dir, "stigmer", "latest", "", NO_IGNORE);
|
|
170
177
|
|
|
@@ -296,7 +303,7 @@ describe("readSkillArchive", () => {
|
|
|
296
303
|
describe("pushSkillFromArchive", () => {
|
|
297
304
|
it("uploads the archive bytes untouched (checksum parity) and applies declared visibility", async () => {
|
|
298
305
|
const zipped = zipSync({
|
|
299
|
-
"SKILL.md": new TextEncoder().encode("---\nname: my-skill\nvisibility:
|
|
306
|
+
"SKILL.md": new TextEncoder().encode("---\nname: my-skill\nvisibility: org\n---\n# S\n"),
|
|
300
307
|
});
|
|
301
308
|
const archivePath = join(dir, "skill.zip");
|
|
302
309
|
writeFileSync(archivePath, zipped);
|
|
@@ -307,7 +314,7 @@ describe("pushSkillFromArchive", () => {
|
|
|
307
314
|
expect(calls.push).toBe(1);
|
|
308
315
|
expect(Buffer.from(calls.pushedArtifacts[0]).equals(Buffer.from(zipped))).toBe(true);
|
|
309
316
|
expect(calls.updateVisibility).toEqual([
|
|
310
|
-
{ resourceId: "skill-123", visibility: ApiResourceVisibility.
|
|
317
|
+
{ resourceId: "skill-123", visibility: ApiResourceVisibility.visibility_org },
|
|
311
318
|
]);
|
|
312
319
|
expect(result.skillName).toBe("my-skill");
|
|
313
320
|
});
|
package/src/resources/skill.ts
CHANGED
|
@@ -95,8 +95,8 @@ interface SkillMetadata {
|
|
|
95
95
|
/**
|
|
96
96
|
* Declared access level, parsed from the optional `visibility:` frontmatter
|
|
97
97
|
* key. `undefined` when omitted — the skill keeps whatever the server already
|
|
98
|
-
* has (default
|
|
99
|
-
*
|
|
98
|
+
* has (the kind's default for new skills). The level is declared with the
|
|
99
|
+
* skill so a push carries it, rather than a second command after.
|
|
100
100
|
*/
|
|
101
101
|
readonly visibility?: ApiResourceVisibility;
|
|
102
102
|
}
|
|
@@ -143,21 +143,29 @@ export function parseSkillMetadataContent(content: string): SkillMetadata {
|
|
|
143
143
|
return { name, visibility: parseVisibility(parsed.visibility, SKILL_FILE) };
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
// Friendly frontmatter spellings → proto enum. Both the short form (`
|
|
147
|
-
// and the canonical enum name (`
|
|
146
|
+
// Friendly frontmatter spellings → proto enum. Both the short form (`org`)
|
|
147
|
+
// and the canonical enum name (`visibility_org`) are accepted so authors can
|
|
148
148
|
// copy either from docs or from generated YAML. `unspecified`/empty is treated
|
|
149
149
|
// as "not declared" (returns undefined) so we never emit a no-op update.
|
|
150
150
|
const VISIBILITY_ALIASES: ReadonlyMap<string, ApiResourceVisibility> = new Map([
|
|
151
151
|
["private", ApiResourceVisibility.visibility_private],
|
|
152
152
|
["visibility_private", ApiResourceVisibility.visibility_private],
|
|
153
|
-
["public", ApiResourceVisibility.visibility_public],
|
|
154
|
-
["visibility_public", ApiResourceVisibility.visibility_public],
|
|
155
153
|
["org", ApiResourceVisibility.visibility_org],
|
|
156
154
|
["visibility_org", ApiResourceVisibility.visibility_org],
|
|
157
155
|
["platform", ApiResourceVisibility.visibility_platform],
|
|
158
156
|
["visibility_platform", ApiResourceVisibility.visibility_platform],
|
|
159
157
|
]);
|
|
160
158
|
|
|
159
|
+
/**
|
|
160
|
+
* The spellings of the retired public level. They are refused like any
|
|
161
|
+
* unknown value, with one extra clause: an author who wrote `public` meant
|
|
162
|
+
* something the platform no longer offers, and the error should say so
|
|
163
|
+
* rather than read as a typo.
|
|
164
|
+
*/
|
|
165
|
+
const RETIRED_VISIBILITY_SPELLINGS: ReadonlySet<string> = new Set(["public", "visibility_public"]);
|
|
166
|
+
|
|
167
|
+
const VALID_VISIBILITY_VALUES = "Valid values: private, org, platform.";
|
|
168
|
+
|
|
161
169
|
/**
|
|
162
170
|
* Map an optional `visibility` frontmatter value to the proto enum. Returns
|
|
163
171
|
* undefined when omitted or explicitly unspecified; throws on an unknown value
|
|
@@ -170,13 +178,17 @@ export function parseVisibility(value: unknown, source = SKILL_FILE): ApiResourc
|
|
|
170
178
|
}
|
|
171
179
|
const key = value.trim().toLowerCase();
|
|
172
180
|
if (key === "" || key === "unspecified" || key === "api_resource_visibility_unspecified") return undefined;
|
|
173
|
-
|
|
174
|
-
if (mapped === undefined) {
|
|
181
|
+
if (RETIRED_VISIBILITY_SPELLINGS.has(key)) {
|
|
175
182
|
throw new UsageError(
|
|
176
|
-
`invalid 'visibility' value '${value}' in ${source}\n\n` +
|
|
177
|
-
"
|
|
183
|
+
`invalid 'visibility' value '${value}' in ${source}: the public level is retired\n\n` +
|
|
184
|
+
"Resources are shared across organizations through plugins, or through the\n" +
|
|
185
|
+
`platform level between organizations linked by one identity provider. ${VALID_VISIBILITY_VALUES}`,
|
|
178
186
|
);
|
|
179
187
|
}
|
|
188
|
+
const mapped = VISIBILITY_ALIASES.get(key);
|
|
189
|
+
if (mapped === undefined) {
|
|
190
|
+
throw new UsageError(`invalid 'visibility' value '${value}' in ${source}\n\n${VALID_VISIBILITY_VALUES}`);
|
|
191
|
+
}
|
|
180
192
|
return mapped;
|
|
181
193
|
}
|
|
182
194
|
|
|
@@ -485,10 +497,9 @@ export async function pushSkillFromArchive(
|
|
|
485
497
|
/**
|
|
486
498
|
* Apply the SKILL.md-declared visibility after a push. The push RPC carries
|
|
487
499
|
* artifact + provenance but not access level (visibility is metadata, not part
|
|
488
|
-
* of the versioned content), so we follow it with a single UpdateVisibility RPC
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
* skipped so an unchanged skill costs nothing extra.
|
|
500
|
+
* of the versioned content), so we follow it with a single UpdateVisibility RPC.
|
|
501
|
+
* No-ops (undefined visibility, or the server already matching) are skipped
|
|
502
|
+
* so an unchanged skill costs nothing extra.
|
|
492
503
|
*/
|
|
493
504
|
async function applyDeclaredVisibility(
|
|
494
505
|
client: Stigmer,
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { type Stigmer } from "@stigmer/sdk";
|
|
2
|
-
import { type ResolveOfficialOptions } from "../../marketplace/official.js";
|
|
3
|
-
import { type PreparedPluginPush } from "../../resources/plugin.js";
|
|
4
|
-
/**
|
|
5
|
-
* The command that ran the install, as the plugin's stored version message
|
|
6
|
-
* names it. Two verbs share the one bootstrap function, and a platform
|
|
7
|
-
* operator reading the row a year later must see which one wrote it.
|
|
8
|
-
*/
|
|
9
|
-
export type InstallingVerb = "stigmer up" | "stigmer bootstrap";
|
|
10
|
-
export interface DefaultPluginsDeps {
|
|
11
|
-
/** The client bound to the backend being bootstrapped. */
|
|
12
|
-
readonly stigmer: Stigmer;
|
|
13
|
-
/** Human progress lines (stderr). */
|
|
14
|
-
readonly info: (line: string) => void;
|
|
15
|
-
/** Stamped into each installed plugin's version message. */
|
|
16
|
-
readonly verb: InstallingVerb;
|
|
17
|
-
}
|
|
18
|
-
/** One default, ready to push: its marketplace name and the prepared archive. */
|
|
19
|
-
export interface PreparedDefault {
|
|
20
|
-
readonly name: string;
|
|
21
|
-
readonly push: PreparedPluginPush;
|
|
22
|
-
}
|
|
23
|
-
export type DefaultPluginOutcome = {
|
|
24
|
-
readonly name: string;
|
|
25
|
-
readonly action: "installed";
|
|
26
|
-
readonly digest: string;
|
|
27
|
-
} | {
|
|
28
|
-
readonly name: string;
|
|
29
|
-
readonly action: "up-to-date";
|
|
30
|
-
readonly digest: string;
|
|
31
|
-
} | {
|
|
32
|
-
readonly name: string;
|
|
33
|
-
readonly action: "failed";
|
|
34
|
-
readonly error: string;
|
|
35
|
-
};
|
|
36
|
-
export interface DefaultPluginsResult {
|
|
37
|
-
readonly outcomes: readonly DefaultPluginOutcome[];
|
|
38
|
-
/** The names that did not land, for the caller's warning. */
|
|
39
|
-
readonly failed: readonly string[];
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Phase 1: every default the official marketplace names, prepared in the
|
|
43
|
-
* marketplace's order. Throws when the tree cannot be resolved, offers less
|
|
44
|
-
* than it lists (the library drops an entry it cannot install with a
|
|
45
|
-
* warning, which for a user's marketplace is `show`'s business and for ours
|
|
46
|
-
* is a broken release), or any default cannot be prepared; nothing is
|
|
47
|
-
* returned half-ready.
|
|
48
|
-
*/
|
|
49
|
-
export declare function prepareDefaultPlugins(official?: ResolveOfficialOptions): Promise<readonly PreparedDefault[]>;
|
|
50
|
-
/**
|
|
51
|
-
* Phase 2: install the prepared defaults into `org`, skipping what the
|
|
52
|
-
* backend already holds. Best-effort per entry.
|
|
53
|
-
*/
|
|
54
|
-
export declare function installPreparedDefaults(deps: DefaultPluginsDeps, prepared: readonly PreparedDefault[], org: string): Promise<DefaultPluginsResult>;
|
|
55
|
-
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../../src/local/plugins/defaults.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,KAAK,OAAO,EAAc,MAAM,cAAc,CAAC;AAOxD,OAAO,EACL,KAAK,sBAAsB,EAE5B,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,2BAA2B,CAAC;AAEnC;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,mBAAmB,CAAC;AAEhE,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,qCAAqC;IACrC,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;CAC/B;AAED,iFAAiF;AACjF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;CACnC;AAED,MAAM,MAAM,oBAAoB,GAC5B;IACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEN,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACnD,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,CAAC,EAAE,sBAAsB,GAChC,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC,CAerC;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,kBAAkB,EACxB,QAAQ,EAAE,SAAS,eAAe,EAAE,EACpC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,oBAAoB,CAAC,CA2B/B"}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
// The default plugins a backend is bootstrapped with: the `defaults` list of
|
|
2
|
-
// the official marketplace, installed in order into the system org as
|
|
3
|
-
// public. The official list is empty today (a session with no agent runs
|
|
4
|
-
// the built-in assistant, so a fresh install needs no default content);
|
|
5
|
-
// the mechanism stays until the bootstrap is re-scoped.
|
|
6
|
-
//
|
|
7
|
-
// Two phases, deliberately separate. Preparing (resolve the official tree,
|
|
8
|
-
// which may acquire `@stigmer/plugins` at the CLI's version; walk, zip and
|
|
9
|
-
// hash every default) needs no backend and is all-or-nothing: the catalogue
|
|
10
|
-
// is ours and validated on CI, so a default that cannot be prepared is a
|
|
11
|
-
// release defect, not a condition to install around. Installing pushes the
|
|
12
|
-
// prepared archives and is best-effort per entry: one default failing to
|
|
13
|
-
// land does not stop the next, and the caller decides how to surface the
|
|
14
|
-
// failures. The split keeps every network read (the catalogue, the
|
|
15
|
-
// archives) ahead of the first write to the backend (local/bootstrap.ts).
|
|
16
|
-
//
|
|
17
|
-
// Idempotent by the server's own identity, not a marker file: before each
|
|
18
|
-
// push the org's plugin of that name is read back; when its digest equals the
|
|
19
|
-
// prepared archive's, it is READY and it is public, there is nothing to do
|
|
20
|
-
// and nothing is sent. A second `stigmer up` therefore pushes nothing, and a
|
|
21
|
-
// `stigmer up` after an upgrade pushes exactly the entries whose content
|
|
22
|
-
// changed. The record is the server, so any machine that reaches the same
|
|
23
|
-
// backend sees the same answer.
|
|
24
|
-
import { isNotFound } from "@stigmer/sdk";
|
|
25
|
-
import { ApiResourceVisibility } from "@stigmer/protos/ai/stigmer/commons/apiresource/enum_pb";
|
|
26
|
-
import { PluginState } from "@stigmer/protos/ai/stigmer/agentic/plugin/v1/status_pb";
|
|
27
|
-
import { CliExitError } from "../../errors/cli-exit-error.js";
|
|
28
|
-
import { ExitCode } from "../../errors/exit-codes.js";
|
|
29
|
-
import { log } from "../../logger.js";
|
|
30
|
-
import { VERSION } from "../../version.js";
|
|
31
|
-
import { resolveOfficialMarketplace, } from "../../marketplace/official.js";
|
|
32
|
-
import { readMarketplaceTree } from "../../marketplace/read.js";
|
|
33
|
-
import { prepareEntry } from "../../marketplace/install.js";
|
|
34
|
-
import { count, pushPrepared, } from "../../resources/plugin.js";
|
|
35
|
-
/**
|
|
36
|
-
* Phase 1: every default the official marketplace names, prepared in the
|
|
37
|
-
* marketplace's order. Throws when the tree cannot be resolved, offers less
|
|
38
|
-
* than it lists (the library drops an entry it cannot install with a
|
|
39
|
-
* warning, which for a user's marketplace is `show`'s business and for ours
|
|
40
|
-
* is a broken release), or any default cannot be prepared; nothing is
|
|
41
|
-
* returned half-ready.
|
|
42
|
-
*/
|
|
43
|
-
export async function prepareDefaultPlugins(official) {
|
|
44
|
-
const resolved = resolveOfficialMarketplace(official);
|
|
45
|
-
const tree = readMarketplaceTree(resolved.dir, "the official marketplace");
|
|
46
|
-
if (tree.warnings.length > 0) {
|
|
47
|
-
throw new CliExitError(`the official marketplace at ${resolved.dir} lists ${count(tree.warnings.length, "plugin")} this CLI cannot install`, ExitCode.General, tree.warnings.map((finding) => finding.message));
|
|
48
|
-
}
|
|
49
|
-
const prepared = [];
|
|
50
|
-
for (const name of tree.marketplace.defaults) {
|
|
51
|
-
prepared.push({ name, push: await prepareEntry(tree, name) });
|
|
52
|
-
}
|
|
53
|
-
return prepared;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Phase 2: install the prepared defaults into `org`, skipping what the
|
|
57
|
-
* backend already holds. Best-effort per entry.
|
|
58
|
-
*/
|
|
59
|
-
export async function installPreparedDefaults(deps, prepared, org) {
|
|
60
|
-
const outcomes = [];
|
|
61
|
-
for (const { name, push } of prepared) {
|
|
62
|
-
try {
|
|
63
|
-
if (await isAlreadyInstalled(deps.stigmer, org, push)) {
|
|
64
|
-
outcomes.push({ name, action: "up-to-date", digest: push.digest });
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
deps.info(`Installing default plugin '${name}'…`);
|
|
68
|
-
await pushPrepared(deps.stigmer, push, {
|
|
69
|
-
org,
|
|
70
|
-
visibility: ApiResourceVisibility.visibility_public,
|
|
71
|
-
message: `default plugin, installed by ${deps.verb} (${VERSION})`,
|
|
72
|
-
});
|
|
73
|
-
outcomes.push({ name, action: "installed", digest: push.digest });
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
77
|
-
log.warn("default plugin install failed", { name, error: message });
|
|
78
|
-
outcomes.push({ name, action: "failed", error: message });
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return {
|
|
82
|
-
outcomes,
|
|
83
|
-
failed: outcomes
|
|
84
|
-
.filter((outcome) => outcome.action === "failed")
|
|
85
|
-
.map((outcome) => outcome.name),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* True when the org already holds this exact archive, materialised and
|
|
90
|
-
* public. A plugin that is absent (NOT_FOUND) installs; one that is present
|
|
91
|
-
* with another digest, still installing, failed, or not public is pushed
|
|
92
|
-
* again, which the server treats as an upgrade or a convergence.
|
|
93
|
-
*/
|
|
94
|
-
async function isAlreadyInstalled(stigmer, org, prepared) {
|
|
95
|
-
let existing;
|
|
96
|
-
try {
|
|
97
|
-
existing = await stigmer.plugin.getByReference({
|
|
98
|
-
org,
|
|
99
|
-
slug: prepared.plugin.name,
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
catch (error) {
|
|
103
|
-
if (isNotFound(error))
|
|
104
|
-
return false;
|
|
105
|
-
throw error;
|
|
106
|
-
}
|
|
107
|
-
return (existing.status?.digest === prepared.digest &&
|
|
108
|
-
existing.status.state === PluginState.READY &&
|
|
109
|
-
existing.metadata?.visibility === ApiResourceVisibility.visibility_public);
|
|
110
|
-
}
|
|
111
|
-
//# sourceMappingURL=defaults.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../../src/local/plugins/defaults.ts"],"names":[],"mappings":"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"}
|
package/local/system-org.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { type Stigmer } from "@stigmer/sdk";
|
|
2
|
-
/** The system organization's slug, identical across editions. */
|
|
3
|
-
export declare const SYSTEM_ORG = "stigmer";
|
|
4
|
-
/**
|
|
5
|
-
* Marks the system org so an operator can tell it from a user's own org in
|
|
6
|
-
* any listing. Informational: no server or client code path reads it.
|
|
7
|
-
*/
|
|
8
|
-
export declare const SYSTEM_ORG_LABEL = "stigmer.ai/system";
|
|
9
|
-
export type EnsureSystemOrgOutcome = "present" | "created";
|
|
10
|
-
/**
|
|
11
|
-
* Make sure the system organization exists on the backend `stigmer` is bound
|
|
12
|
-
* to. Idempotent; a lost create race counts as `present`.
|
|
13
|
-
*/
|
|
14
|
-
export declare function ensureSystemOrg(stigmer: Stigmer): Promise<EnsureSystemOrgOutcome>;
|
|
15
|
-
//# sourceMappingURL=system-org.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"system-org.d.ts","sourceRoot":"","sources":["../../src/local/system-org.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,KAAK,OAAO,EAAgB,MAAM,cAAc,CAAC;AAE1D,iEAAiE;AACjE,eAAO,MAAM,UAAU,YAAY,CAAC;AAEpC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AAEpD,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,SAAS,CAAC;AAE3D;;;GAGG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,sBAAsB,CAAC,CAuBjC"}
|