@frockbot/plugin-bot-template 0.1.3 → 0.1.4
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/package.json +11 -11
- package/src/agent.ts +1 -1
- package/src/client/BotTemplateImportSection.vue +8 -9
- package/src/client/BotTemplateSection.vue +3 -3
- package/src/import-apply.test.ts +1 -2
- package/src/import.test.ts +2 -3
- package/src/import.ts +6 -7
- package/src/scrub.test.ts +1 -6
- package/src/scrub.ts +4 -11
- package/src/shared.ts +3 -5
- package/src/user.test.ts +1 -11
- package/src/user.ts +1 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frockbot/plugin-bot-template",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -24,20 +24,20 @@
|
|
|
24
24
|
"typecheck": "vue-tsc --noEmit -p tsconfig.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@frockbot/client-core": "0.1.
|
|
28
|
-
"@frockbot/client-ui": "0.1.
|
|
29
|
-
"@frockbot/configuration-core": "0.1.
|
|
30
|
-
"@frockbot/connection-core": "0.1.
|
|
31
|
-
"@frockbot/kernel-agent-loop": "0.1.
|
|
32
|
-
"@frockbot/kernel-contracts": "0.1.
|
|
33
|
-
"@frockbot/plugin-settings": "0.1.
|
|
34
|
-
"@frockbot/plugin-shell": "0.1.
|
|
35
|
-
"@frockbot/template-core": "0.1.
|
|
27
|
+
"@frockbot/client-core": "0.1.4",
|
|
28
|
+
"@frockbot/client-ui": "0.1.4",
|
|
29
|
+
"@frockbot/configuration-core": "0.1.4",
|
|
30
|
+
"@frockbot/connection-core": "0.1.4",
|
|
31
|
+
"@frockbot/kernel-agent-loop": "0.1.4",
|
|
32
|
+
"@frockbot/kernel-contracts": "0.1.4",
|
|
33
|
+
"@frockbot/plugin-settings": "0.1.4",
|
|
34
|
+
"@frockbot/plugin-shell": "0.1.4",
|
|
35
|
+
"@frockbot/template-core": "0.1.4",
|
|
36
36
|
"cordis": "4.0.0-rc.8",
|
|
37
37
|
"vue": "3.5.41"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@frockbot/plugin-tools": "0.1.
|
|
40
|
+
"@frockbot/plugin-tools": "0.1.4",
|
|
41
41
|
"@types/bun": "1.4.0",
|
|
42
42
|
"@vitejs/plugin-vue": "6.0.8",
|
|
43
43
|
"typescript": "5.9.3",
|
package/src/agent.ts
CHANGED
|
@@ -122,7 +122,7 @@ const DESCRIPTION = [
|
|
|
122
122
|
"Pack yourself into a shareable Bot template: a recipe, not a backup.",
|
|
123
123
|
"It carries your name, description, your own Skills, your Routines' prompts,",
|
|
124
124
|
"the Catalog Packages your User installed, and public MCP server addresses.",
|
|
125
|
-
"It never carries Memory, credentials, Connections,
|
|
125
|
+
"It never carries Memory, credentials, Connections, your model,",
|
|
126
126
|
"webhook keys, uploaded images, or anything from your Computer.",
|
|
127
127
|
"The template is staged privately and shared with nobody:",
|
|
128
128
|
"only your User can choose to publish it, from Bot settings.",
|
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
//
|
|
4
4
|
// The review card is the whole point of this surface. A template is prose from
|
|
5
5
|
// a stranger, and it names Packages, Skills and Routines that are about to
|
|
6
|
-
// become
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// pressed.
|
|
6
|
+
// become part of this User's account — so it is shown as four honest sections
|
|
7
|
+
// before anything happens, and `Create the Bot` is the only control that
|
|
8
|
+
// writes. Planning is a read; the record stays `planned` until it is pressed.
|
|
10
9
|
//
|
|
11
10
|
// What the card never offers is a way to connect anything. An import creates no
|
|
12
|
-
// Connection
|
|
13
|
-
//
|
|
11
|
+
// Connection or credential, so "Needs your own Connection" is a list of things
|
|
12
|
+
// the User must go and do themselves, not a checkbox.
|
|
14
13
|
import { UiButton, UiField, UiIcon } from "@frockbot/client-ui";
|
|
15
14
|
import { computed, inject, ref } from "vue";
|
|
16
15
|
import { botTemplateStateKey } from "./state.js";
|
|
@@ -73,7 +72,7 @@ async function plan(): Promise<void> {
|
|
|
73
72
|
<small>
|
|
74
73
|
Paste a template link to see exactly what it would create before
|
|
75
74
|
anything happens. Importing never brings across Memory, credentials,
|
|
76
|
-
|
|
75
|
+
or Connections.
|
|
77
76
|
</small>
|
|
78
77
|
</span>
|
|
79
78
|
</header>
|
|
@@ -167,8 +166,8 @@ async function plan(): Promise<void> {
|
|
|
167
166
|
</li>
|
|
168
167
|
</ul>
|
|
169
168
|
<p class="import__note">
|
|
170
|
-
None of these is created for you. Add each one
|
|
171
|
-
it to
|
|
169
|
+
None of these is created for you. Add each one in Connectors; once
|
|
170
|
+
enabled, it is available to every Bot you own.
|
|
172
171
|
</p>
|
|
173
172
|
</section>
|
|
174
173
|
|
|
@@ -102,8 +102,8 @@ async function copyLink(share: TemplateShareRecordV1): Promise<void> {
|
|
|
102
102
|
<strong>Share this Bot</strong>
|
|
103
103
|
<small>
|
|
104
104
|
Packs the profile, Bot-authored Skills, Routines, and required
|
|
105
|
-
Packages. Memory, credentials, Connections,
|
|
106
|
-
|
|
105
|
+
Packages. Memory, credentials, Connections, and Computer files stay
|
|
106
|
+
private.
|
|
107
107
|
</small>
|
|
108
108
|
</span>
|
|
109
109
|
<UiButton
|
|
@@ -131,7 +131,7 @@ async function copyLink(share: TemplateShareRecordV1): Promise<void> {
|
|
|
131
131
|
{{ templates.summary.needsConnection }} server(s) are left as a
|
|
132
132
|
placeholder the importer fills with their own Connection.
|
|
133
133
|
</template>
|
|
134
|
-
Memory, credentials,
|
|
134
|
+
Memory, credentials, and Connections were not included.
|
|
135
135
|
</p>
|
|
136
136
|
|
|
137
137
|
<p
|
package/src/import-apply.test.ts
CHANGED
|
@@ -366,14 +366,13 @@ describe("applying", () => {
|
|
|
366
366
|
expect(Object.keys(recording.installs[0]!)).not.toContain("values");
|
|
367
367
|
});
|
|
368
368
|
|
|
369
|
-
it("creates no Connection
|
|
369
|
+
it("creates no Connection or credential", async () => {
|
|
370
370
|
const { contribution, recording } = await harness();
|
|
371
371
|
await plan(contribution);
|
|
372
372
|
const applied = await apply(contribution);
|
|
373
373
|
expect(recording.calls.some((call) => call.includes("connection"))).toBe(
|
|
374
374
|
false,
|
|
375
375
|
);
|
|
376
|
-
expect(JSON.stringify(applied)).not.toContain("assignmentId");
|
|
377
376
|
expect(applied.connections[0]!.name).toBe("Beeper");
|
|
378
377
|
});
|
|
379
378
|
});
|
package/src/import.test.ts
CHANGED
|
@@ -187,7 +187,7 @@ describe("the step list", () => {
|
|
|
187
187
|
});
|
|
188
188
|
|
|
189
189
|
describe("what an import never does", () => {
|
|
190
|
-
it("plans no Connection
|
|
190
|
+
it("plans no Connection or credential, only lines telling the User", () => {
|
|
191
191
|
const plan = planBotTemplateImportV1(input());
|
|
192
192
|
expect(plan.connections).toEqual([
|
|
193
193
|
{
|
|
@@ -199,7 +199,6 @@ describe("what an import never does", () => {
|
|
|
199
199
|
expect(plan.steps.some((step) => step.kind.includes("connection"))).toBe(
|
|
200
200
|
false,
|
|
201
201
|
);
|
|
202
|
-
expect(JSON.stringify(plan)).not.toContain("assignment");
|
|
203
202
|
});
|
|
204
203
|
|
|
205
204
|
it("lists a public server too, because no Connection is created for it", () => {
|
|
@@ -261,6 +260,6 @@ describe("the card's prose", () => {
|
|
|
261
260
|
expect(described).toContain('Will create the Bot "Budget"');
|
|
262
261
|
expect(described).toContain("missing from your catalog");
|
|
263
262
|
expect(described).toContain("need your own Connection");
|
|
264
|
-
expect(described).toContain("No Connection
|
|
263
|
+
expect(described).toContain("No Connection or credential");
|
|
265
264
|
});
|
|
266
265
|
});
|
package/src/import.ts
CHANGED
|
@@ -10,12 +10,11 @@
|
|
|
10
10
|
// off a moved index: "Composition consumes immutable, content-addressed
|
|
11
11
|
// artifacts", and an install validated against anything else is not that.
|
|
12
12
|
//
|
|
13
|
-
// WHAT IMPORT NEVER CREATES. No Connection
|
|
14
|
-
//
|
|
15
|
-
// explicit
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
// card telling the User what they would have to connect themselves.
|
|
13
|
+
// WHAT IMPORT NEVER CREATES. No Connection or credential. An enabled Package
|
|
14
|
+
// is available account-wide, while Connections remain the importing User's
|
|
15
|
+
// explicit choice. A template is a recipe that stops at that authority
|
|
16
|
+
// boundary. Every server it names becomes a line on the card telling the User
|
|
17
|
+
// what they would have to connect themselves.
|
|
19
18
|
import type {
|
|
20
19
|
BotTemplateV1,
|
|
21
20
|
TemplateSheepRecipeV1,
|
|
@@ -274,7 +273,7 @@ export function describeImportPlanV1(plan: TemplateImportPlanV1): string {
|
|
|
274
273
|
plan.connections.length > 0
|
|
275
274
|
? `${plan.connections.length} server(s) need your own Connection; none is created for you.`
|
|
276
275
|
: "",
|
|
277
|
-
"No Connection
|
|
276
|
+
"No Connection or credential is created by an import.",
|
|
278
277
|
]
|
|
279
278
|
.filter(Boolean)
|
|
280
279
|
.join(" ");
|
package/src/scrub.test.ts
CHANGED
|
@@ -428,21 +428,16 @@ describe("MCP servers and Connections", () => {
|
|
|
428
428
|
expect(omitted(summary, "private-network-server")).toBe(1);
|
|
429
429
|
});
|
|
430
430
|
|
|
431
|
-
it("never carries a connectionId
|
|
431
|
+
it("never carries a connectionId or safeMetadata", () => {
|
|
432
432
|
const { template, summary } = buildBotTemplateV1(
|
|
433
433
|
source({
|
|
434
434
|
connections: [publicServer, keyedServer],
|
|
435
|
-
assignmentCount: 3,
|
|
436
|
-
hasModelAssignment: true,
|
|
437
435
|
}),
|
|
438
436
|
);
|
|
439
437
|
const document = JSON.stringify(template);
|
|
440
438
|
expect(document).not.toContain("connectionId");
|
|
441
439
|
expect(document).not.toContain("safeMetadata");
|
|
442
|
-
expect(document).not.toContain("assignment");
|
|
443
440
|
expect(omitted(summary, "connection")).toBe(2);
|
|
444
|
-
expect(omitted(summary, "assignment")).toBe(3);
|
|
445
|
-
expect(omitted(summary, "model")).toBe(1);
|
|
446
441
|
});
|
|
447
442
|
|
|
448
443
|
it("omits a Connection that names no server endpoint", () => {
|
package/src/scrub.ts
CHANGED
|
@@ -17,11 +17,10 @@
|
|
|
17
17
|
// Memory, transcripts, unread state, Computer files a template is
|
|
18
18
|
// public-shareable and Memory is the User's facts under a durable root
|
|
19
19
|
// (ADR 0015 records the divergence from GrokBot's `memory:[…]`).
|
|
20
|
-
// Connections, `connectionId`, `safeMetadata
|
|
21
|
-
//
|
|
22
|
-
// required, a Connection." An import must not inherit either.
|
|
20
|
+
// Connections, `connectionId`, `safeMetadata` Connections belong to the
|
|
21
|
+
// importing User and cannot cross Users.
|
|
23
22
|
// `PackageInstallationView.values` setup fields may hold keys.
|
|
24
|
-
//
|
|
23
|
+
// Bot-scoped Package values they may name a Connection.
|
|
25
24
|
import {
|
|
26
25
|
MAX_TEMPLATE_ROUTINE_PROMPT_BYTES_V1,
|
|
27
26
|
MAX_TEMPLATE_SKILL_BODY_BYTES_V1,
|
|
@@ -123,10 +122,6 @@ export interface TemplateSourceV1 {
|
|
|
123
122
|
routines: readonly TemplateRoutineCandidateV1[];
|
|
124
123
|
packages: readonly TemplatePackageCandidateV1[];
|
|
125
124
|
connections: readonly TemplateConnectionCandidateV1[];
|
|
126
|
-
/** True when the Bot has a model assignment; it names a Connection, so it goes. */
|
|
127
|
-
hasModelAssignment?: boolean;
|
|
128
|
-
/** How many Assignments the Bot holds; counted, never carried. */
|
|
129
|
-
assignmentCount?: number;
|
|
130
125
|
sourceCatalogGeneration?: string;
|
|
131
126
|
}
|
|
132
127
|
|
|
@@ -434,8 +429,6 @@ export function buildBotTemplateV1(
|
|
|
434
429
|
source: TemplateSourceV1,
|
|
435
430
|
): TemplateBuildResultV1 {
|
|
436
431
|
const omissions = new Omissions();
|
|
437
|
-
if (source.hasModelAssignment) omissions.add("model");
|
|
438
|
-
omissions.add("assignment", source.assignmentCount ?? 0);
|
|
439
432
|
// Memory is never read, so there is nothing to count; the omission is
|
|
440
433
|
// recorded unconditionally because it is the one a User most needs told.
|
|
441
434
|
omissions.add("memory");
|
|
@@ -495,7 +488,7 @@ export function describeTemplateSummaryV1(
|
|
|
495
488
|
`${summary.packages} Package${summary.packages === 1 ? "" : "s"}`,
|
|
496
489
|
`${summary.publicServers} public MCP server${summary.publicServers === 1 ? "" : "s"}`,
|
|
497
490
|
].join(", ");
|
|
498
|
-
const scrubbed: string[] = ["Memory", "Connections"
|
|
491
|
+
const scrubbed: string[] = ["Memory", "Connections"];
|
|
499
492
|
if (summary.needsConnection > 0) {
|
|
500
493
|
scrubbed.push(
|
|
501
494
|
`${summary.needsConnection} server${summary.needsConnection === 1 ? "" : "s"} left as a placeholder`,
|
package/src/shared.ts
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
// is the traffic around it: the commands a User issues, the receipts they get
|
|
8
8
|
// back, and the summary of what an export packed and what it scrubbed.
|
|
9
9
|
//
|
|
10
|
-
// Nothing here carries a credential, a `connectionId`,
|
|
11
|
-
//
|
|
12
|
-
//
|
|
10
|
+
// Nothing here carries a credential, a `connectionId`, or a webhook key, and
|
|
11
|
+
// the decoders refuse an unknown key, so a shape that grew one would fail at
|
|
12
|
+
// the seam rather than travel.
|
|
13
13
|
import {
|
|
14
14
|
decodeTemplateShareRecordV1,
|
|
15
15
|
decodeTemplateVisibilityV1,
|
|
@@ -30,8 +30,6 @@ export const TEMPLATE_OMISSION_REASONS_V1 = [
|
|
|
30
30
|
"first-party-package",
|
|
31
31
|
"package-values",
|
|
32
32
|
"connection",
|
|
33
|
-
"assignment",
|
|
34
|
-
"model",
|
|
35
33
|
"memory",
|
|
36
34
|
"private-network-server",
|
|
37
35
|
] as const;
|
package/src/user.test.ts
CHANGED
|
@@ -92,17 +92,7 @@ function botSettings(): BotSettingsViewV1 {
|
|
|
92
92
|
revision: 3,
|
|
93
93
|
profile: { name: "Budget", title: "Money minder" },
|
|
94
94
|
notifications: { enabled: true },
|
|
95
|
-
|
|
96
|
-
{
|
|
97
|
-
assignmentId: "a-1",
|
|
98
|
-
packageId: "mcp",
|
|
99
|
-
capabilityId: "mcp-tools",
|
|
100
|
-
connectionId: "connection-1",
|
|
101
|
-
state: "enabled",
|
|
102
|
-
},
|
|
103
|
-
],
|
|
104
|
-
assignmentOperations: [],
|
|
105
|
-
model: { connectionId: "connection-1", providerModelId: "glm" },
|
|
95
|
+
packageValues: {},
|
|
106
96
|
};
|
|
107
97
|
}
|
|
108
98
|
|
package/src/user.ts
CHANGED
|
@@ -112,7 +112,7 @@ export interface TemplateBotReaderV1 {
|
|
|
112
112
|
* Every method is a command the importing User's own surfaces already issue —
|
|
113
113
|
* `bot/create` from the sidebar, `user/install-package` from the Plugins
|
|
114
114
|
* surface, a Skill write and a `routine/create` from the Bot's own settings.
|
|
115
|
-
* There is deliberately nothing here for a Connection or
|
|
115
|
+
* There is deliberately nothing here for a Connection or credential: an
|
|
116
116
|
* import cannot create either, because this seam cannot express it.
|
|
117
117
|
*/
|
|
118
118
|
export interface TemplateImportWriterV1 {
|
|
@@ -442,8 +442,6 @@ export class BotTemplateUserBackendContribution {
|
|
|
442
442
|
},
|
|
443
443
|
}),
|
|
444
444
|
})),
|
|
445
|
-
hasModelAssignment: settings.model !== undefined,
|
|
446
|
-
assignmentCount: settings.assignments.length,
|
|
447
445
|
...(user.catalogGeneration === undefined
|
|
448
446
|
? {}
|
|
449
447
|
: { sourceCatalogGeneration: user.catalogGeneration }),
|