@pasko70/pibo 1.0.5 → 1.1.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/README.md +5 -1
- package/dist/apps/chat/agent-profiles.js +26 -4
- package/dist/apps/chat/model-catalog.js +42 -0
- package/dist/apps/chat/web-app.js +192 -7
- package/dist/apps/chat-ui/assets/{dist-aMr2VYOu.js → dist-8e4L8ciw.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BGxHKHPX.js → dist-B7bbI3Qz.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-u2OzzOTm.js → dist-CMZOa5ik.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CI0Xj2Cp.js → dist-CNLWH2qh.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-zgYUl2B-.js → dist-CUqpST5w.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-wiRpAHIv.js → dist-CqqUC8Ce.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CNlhGq5i.js → dist-CspjOeBj.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CaNOvqMY.js → dist-D2N4-LIc.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DpmEro5R.js → dist-D9L4MSRF.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Di1ScJ22.js → dist-DNcnQRPF.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DrM-H3e1.js → dist-v4pjHlB7.js} +1 -1
- package/dist/apps/chat-ui/assets/index-D2Qxambd.js +151 -0
- package/dist/apps/chat-ui/assets/{index-Dk-opWl3.css → index-DXx368XK.css} +1 -1
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/gateway/server.js +2 -0
- package/dist/plugins/builtin.js +2 -1
- package/dist/plugins/registry.js +17 -1
- package/dist/user-skills/installer.js +211 -0
- package/dist/user-skills/manager.js +35 -0
- package/dist/user-skills/store.js +228 -0
- package/dist/user-skills/types.js +1 -0
- package/package.json +3 -3
- package/dist/apps/chat-ui/assets/index-B_E935fP.js +0 -151
- /package/{.codex/skills → skills/builtin}/pi-agent-harness/SKILL.md +0 -0
- /package/{.codex/skills → skills/builtin}/pi-agent-harness/agents/openai.yaml +0 -0
package/README.md
CHANGED
|
@@ -111,6 +111,10 @@ Custom agents can be archived before deletion. Archived custom agents are remove
|
|
|
111
111
|
|
|
112
112
|
The designer configures native Pibo agent capabilities only: plugin-registered tools, skills, context files, subagents, automatic local context-file loading, built-in Pi tool visibility, and capability packages such as `pibo-run-control`. Curated external CLI tools from `pibo tools` remain global operator tooling and are not selected per agent.
|
|
113
113
|
|
|
114
|
+
The Chat Web App also supports User Skills. Operators can create local skills or import them from `skills.sh` or GitHub, and Pibo stores them under `.pibo/user-skills` plus `.pibo/user-skills.json`. Enabled user skills are registered live so they are selectable in the Agent Designer and available to routed sessions without a manual restart.
|
|
115
|
+
|
|
116
|
+
User Skill names are guarded at two layers: the web app no longer re-registers an already-synced skill on subsequent requests, and create/rename/enable/import flows reject names that would collide with an already registered skill. Imports also refuse to silently overwrite an existing skill name.
|
|
117
|
+
|
|
114
118
|
The Chat Web App now also has a dedicated Context area at `/apps/chat/context`. It reuses the managed context-file APIs inside the main Chat UI shell so operators can create, edit, relocate, and remove managed context files without leaving the authenticated Chat Web App. Plugin context files are shown there as read-only sources, and both the Context area and Agent Designer can create linked managed copies when a user wants to customize shipped content safely.
|
|
115
119
|
|
|
116
120
|
The Context area also exposes the Pibo Base Prompt. The library prompt lives at `context/pibo-system-prompt.md`; the Chat Web App can switch between that read-only library prompt and a persisted custom prompt stored under `.pibo/base-prompt.md`. Runtime prompt templates replace `{{availableTools}}` and `{{guidelines}}` from the active Pi/Pibo tool surface before project context and skills are appended.
|
|
@@ -119,7 +123,7 @@ The Context area also exposes the Pibo Compaction Prompt. The library prompt liv
|
|
|
119
123
|
|
|
120
124
|
## Profiles
|
|
121
125
|
|
|
122
|
-
The default profile is registered by the core plugin. It loads the
|
|
126
|
+
The default profile is registered by the core plugin. It loads the built-in `pi-agent-harness` skill from `skills/builtin/pi-agent-harness/SKILL.md` and uses Pi Coding Agent's built-in tools for normal coding work.
|
|
123
127
|
|
|
124
128
|
The `codex` alias resolves to the `codex-compat-openai-web` profile. It keeps the Pibo runtime boundary while exposing Codex-like coding affordances: Pi/Pibo `read`, `edit`, and `write`; Pibo run-control `bash`; native `web_search`; `apply_patch` and `view_image`; generated `pibo_subagent_default`, `pibo_subagent_explorer`, and `pibo_subagent_worker`; and the `pibo_run_*` lifecycle tools. `web_search` is a normal Pibo native tool with a provider adapter; the default adapter injects OpenAI Responses hosted `web_search` into the model request instead of using a local DuckDuckGo function tool. It intentionally does not expose Pi's separate `grep`, `find`, or `ls` tools by default; codebase search remains Codex-style through `bash` and commands such as `rg`.
|
|
125
129
|
|
|
@@ -16,10 +16,26 @@ export function createCustomAgentProfileDefinition(agent) {
|
|
|
16
16
|
builder.withMainModel(agent.mainModel);
|
|
17
17
|
if (agent.subagentModel)
|
|
18
18
|
builder.withSubagentModel(agent.subagentModel);
|
|
19
|
-
for (const skillName of agent.skills)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
for (const skillName of agent.skills) {
|
|
20
|
+
try {
|
|
21
|
+
builder.addSkill(context.getSkill(skillName));
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (!isUnknownSkillError(error, skillName))
|
|
25
|
+
throw error;
|
|
26
|
+
console.warn(`Skipping unknown skill "${skillName}" for custom agent "${agent.profileName}"`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
for (const contextFileKey of agent.contextFiles) {
|
|
30
|
+
try {
|
|
31
|
+
builder.addContextFile(context.getContextFile(contextFileKey));
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (!isUnknownContextFileError(error, contextFileKey))
|
|
35
|
+
throw error;
|
|
36
|
+
console.warn(`Skipping unknown context file "${contextFileKey}" for custom agent "${agent.profileName}"`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
23
39
|
for (const toolName of agent.nativeTools)
|
|
24
40
|
builder.addTool(context.getTool(toolName));
|
|
25
41
|
for (const subagent of agent.subagents)
|
|
@@ -28,3 +44,9 @@ export function createCustomAgentProfileDefinition(agent) {
|
|
|
28
44
|
},
|
|
29
45
|
};
|
|
30
46
|
}
|
|
47
|
+
function isUnknownContextFileError(error, contextFileKey) {
|
|
48
|
+
return error instanceof Error && error.message === `Unknown context file "${contextFileKey}"`;
|
|
49
|
+
}
|
|
50
|
+
function isUnknownSkillError(error, skillName) {
|
|
51
|
+
return error instanceof Error && error.message === `Unknown skill "${skillName}"`;
|
|
52
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createAgentSessionServices } from "@mariozechner/pi-coding-agent";
|
|
2
|
+
export function buildModelCatalogFromRegistry(registry) {
|
|
3
|
+
const providers = new Map();
|
|
4
|
+
for (const model of registry.getAll()) {
|
|
5
|
+
const providerId = model.provider;
|
|
6
|
+
let provider = providers.get(providerId);
|
|
7
|
+
if (!provider) {
|
|
8
|
+
const authConfigured = registry.getProviderAuthStatus?.(providerId).configured ?? false;
|
|
9
|
+
provider = {
|
|
10
|
+
id: providerId,
|
|
11
|
+
label: registry.getProviderDisplayName?.(providerId) ?? providerId,
|
|
12
|
+
authConfigured,
|
|
13
|
+
models: [],
|
|
14
|
+
};
|
|
15
|
+
providers.set(providerId, provider);
|
|
16
|
+
}
|
|
17
|
+
provider.models.push({
|
|
18
|
+
provider: providerId,
|
|
19
|
+
id: model.id,
|
|
20
|
+
label: model.name || model.id,
|
|
21
|
+
authConfigured: provider.authConfigured,
|
|
22
|
+
supportsReasoning: model.reasoning || undefined,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
providers: [...providers.values()]
|
|
27
|
+
.sort((left, right) => left.label.localeCompare(right.label) || left.id.localeCompare(right.id))
|
|
28
|
+
.map((provider) => ({
|
|
29
|
+
...provider,
|
|
30
|
+
models: [...provider.models].sort((left, right) => left.label.localeCompare(right.label) || left.id.localeCompare(right.id)),
|
|
31
|
+
})),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export async function loadModelCatalog(cwd = process.cwd()) {
|
|
35
|
+
try {
|
|
36
|
+
const services = await createAgentSessionServices({ cwd });
|
|
37
|
+
return buildModelCatalogFromRegistry(services.modelRegistry);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return { providers: [] };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -13,6 +13,7 @@ import { isChatWebSessionArchived, withChatWebArchived } from "./session-metadat
|
|
|
13
13
|
import { CustomAgentStore, createDefaultCustomAgentStore, isValidCustomAgentName, } from "./agent-store.js";
|
|
14
14
|
import { loadPiboModelDefaults, savePiboModelDefaults, } from "../../core/model-defaults.js";
|
|
15
15
|
import { createCustomAgentProfileDefinition } from "./agent-profiles.js";
|
|
16
|
+
import { loadModelCatalog } from "./model-catalog.js";
|
|
16
17
|
import { createDefaultPiboReliabilityStore, PiboReliabilityStore } from "../../reliability/store.js";
|
|
17
18
|
import { listMcpServerInfos, setMcpServerDescription } from "../../mcp/agent-context.js";
|
|
18
19
|
import { readPiboBasePrompt, savePiboCustomBasePrompt, setPiboBasePromptMode, } from "../../core/base-prompt.js";
|
|
@@ -20,6 +21,7 @@ import { readPiboCompactionPrompt, savePiboCustomCompactionPrompt, setPiboCompac
|
|
|
20
21
|
import { getDefaultPiboWorkspace } from "../../core/workspace.js";
|
|
21
22
|
import { inspectPiPackageSource } from "../../pi-packages/metadata.js";
|
|
22
23
|
import { findPiPackage, listPiPackages, removePiPackage, setPiPackageEnabled, upsertPiPackage } from "../../pi-packages/store.js";
|
|
24
|
+
import { UserSkillManager } from "../../user-skills/manager.js";
|
|
23
25
|
export const CHAT_WEB_APP_NAME = "pibo.chat-web";
|
|
24
26
|
export const CHAT_WEB_CHANNEL = "pibo.chat-web";
|
|
25
27
|
export const CHAT_WEB_MOUNT_PATH = "/apps/chat";
|
|
@@ -390,6 +392,59 @@ function normalizeCompactionPromptMarkdown(value) {
|
|
|
390
392
|
throw new PiboWebHttpError("markdown must be a string", 400);
|
|
391
393
|
return value;
|
|
392
394
|
}
|
|
395
|
+
function normalizeUserSkillName(value) {
|
|
396
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
397
|
+
throw new PiboWebHttpError("Skill name is required", 400);
|
|
398
|
+
}
|
|
399
|
+
const name = value.trim();
|
|
400
|
+
if (name.length > 64)
|
|
401
|
+
throw new PiboWebHttpError("Skill name is too long", 400);
|
|
402
|
+
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
|
|
403
|
+
throw new PiboWebHttpError("Skill name must be lowercase kebab-case, e.g. my-skill", 400);
|
|
404
|
+
}
|
|
405
|
+
return name;
|
|
406
|
+
}
|
|
407
|
+
function normalizeUserSkillDescription(value) {
|
|
408
|
+
if (typeof value !== "string")
|
|
409
|
+
throw new PiboWebHttpError("Skill description must be a string", 400);
|
|
410
|
+
return value.trim();
|
|
411
|
+
}
|
|
412
|
+
function normalizeUserSkillMarkdown(value) {
|
|
413
|
+
if (typeof value !== "string")
|
|
414
|
+
throw new PiboWebHttpError("Skill markdown must be a string", 400);
|
|
415
|
+
return value;
|
|
416
|
+
}
|
|
417
|
+
function normalizeUserSkillEnabled(value) {
|
|
418
|
+
if (value === undefined)
|
|
419
|
+
return undefined;
|
|
420
|
+
if (typeof value !== "boolean")
|
|
421
|
+
throw new PiboWebHttpError("enabled must be a boolean", 400);
|
|
422
|
+
return value;
|
|
423
|
+
}
|
|
424
|
+
function normalizeUserSkillUrl(value) {
|
|
425
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
426
|
+
throw new PiboWebHttpError("Skill URL is required", 400);
|
|
427
|
+
}
|
|
428
|
+
const url = value.trim();
|
|
429
|
+
if (!url.startsWith("http://") && !url.startsWith("https://") && !url.includes("/")) {
|
|
430
|
+
throw new PiboWebHttpError("Skill URL must be a valid URL or owner/repo shorthand", 400);
|
|
431
|
+
}
|
|
432
|
+
return url;
|
|
433
|
+
}
|
|
434
|
+
function userSkillResourceId(pathname) {
|
|
435
|
+
const prefix = `${CHAT_WEB_API_PREFIX}/user-skills/`;
|
|
436
|
+
if (!pathname.startsWith(prefix))
|
|
437
|
+
return undefined;
|
|
438
|
+
const encodedId = pathname.slice(prefix.length);
|
|
439
|
+
if (!encodedId || encodedId.includes("/"))
|
|
440
|
+
return undefined;
|
|
441
|
+
try {
|
|
442
|
+
return decodeURIComponent(encodedId);
|
|
443
|
+
}
|
|
444
|
+
catch {
|
|
445
|
+
throw new PiboWebHttpError("Invalid user skill id", 400);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
393
448
|
function normalizeAgentArchived(value) {
|
|
394
449
|
if (value === undefined)
|
|
395
450
|
return undefined;
|
|
@@ -743,6 +798,52 @@ function ensureCustomAgentProfiles(state, context) {
|
|
|
743
798
|
context.channelContext.upsertProfile(createCustomAgentProfileDefinition(agent));
|
|
744
799
|
}
|
|
745
800
|
}
|
|
801
|
+
function serializeCustomAgent(agent, context) {
|
|
802
|
+
return {
|
|
803
|
+
...agent,
|
|
804
|
+
brokenContextFiles: listBrokenContextFiles(agent.contextFiles, context),
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
function serializeCustomAgents(agents, context) {
|
|
808
|
+
return agents.map((agent) => serializeCustomAgent(agent, context));
|
|
809
|
+
}
|
|
810
|
+
function listBrokenContextFiles(keys, context) {
|
|
811
|
+
const catalog = context.channelContext.getCapabilityCatalog?.();
|
|
812
|
+
if (!catalog)
|
|
813
|
+
return [];
|
|
814
|
+
const knownKeys = new Set(catalog.contextFiles.map((contextFile) => contextFile.key));
|
|
815
|
+
return keys.filter((key) => !knownKeys.has(key));
|
|
816
|
+
}
|
|
817
|
+
function syncUserSkills(state, context) {
|
|
818
|
+
const registerSkill = context.channelContext.registerSkill;
|
|
819
|
+
const unregisterSkill = context.channelContext.unregisterSkill;
|
|
820
|
+
if (!registerSkill || !unregisterSkill)
|
|
821
|
+
return;
|
|
822
|
+
const userSkills = state.userSkillManager.list();
|
|
823
|
+
const enabledNames = new Set(userSkills.filter((s) => s.enabled).map((s) => s.name));
|
|
824
|
+
const previouslySyncedNames = state.syncedUserSkillNames ?? new Set();
|
|
825
|
+
// Unregister disabled or removed user skills
|
|
826
|
+
for (const name of previouslySyncedNames) {
|
|
827
|
+
if (!enabledNames.has(name)) {
|
|
828
|
+
unregisterSkill(name);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
// Register only newly enabled user skills. Re-registering an already synced
|
|
832
|
+
// skill would trip the registry duplicate-skill guard and break the web UI.
|
|
833
|
+
for (const skill of userSkills) {
|
|
834
|
+
if (skill.enabled && !previouslySyncedNames.has(skill.name)) {
|
|
835
|
+
registerSkill({ name: skill.name, path: skill.path, enabled: true });
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
state.syncedUserSkillNames = enabledNames;
|
|
839
|
+
}
|
|
840
|
+
function assertUserSkillNameIsAvailable(state, context, name, currentSkillId) {
|
|
841
|
+
const currentSkill = currentSkillId ? state.userSkillManager.get(currentSkillId) : undefined;
|
|
842
|
+
const conflict = (context.channelContext.getCapabilityCatalog?.().skills ?? []).find((skill) => (skill.name === name && (!currentSkill || currentSkill.name !== name)));
|
|
843
|
+
if (conflict) {
|
|
844
|
+
throw new PiboWebHttpError(`Skill name "${name}" conflicts with an existing registered skill`, 409);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
746
847
|
function createAgentInput(ownerScope, body) {
|
|
747
848
|
return {
|
|
748
849
|
ownerScope,
|
|
@@ -816,7 +917,7 @@ function requireOwnedAgent(agent, webSession) {
|
|
|
816
917
|
}
|
|
817
918
|
return agent;
|
|
818
919
|
}
|
|
819
|
-
async function buildAgentCatalog(context) {
|
|
920
|
+
async function buildAgentCatalog(context, state) {
|
|
820
921
|
return {
|
|
821
922
|
...(context.channelContext.getCapabilityCatalog?.() ?? {
|
|
822
923
|
nativeTools: [],
|
|
@@ -830,6 +931,7 @@ async function buildAgentCatalog(context) {
|
|
|
830
931
|
}),
|
|
831
932
|
mcpServers: await listMcpServerInfos(),
|
|
832
933
|
piPackages: listPiPackages(),
|
|
934
|
+
userSkills: state.userSkillManager.list(),
|
|
833
935
|
};
|
|
834
936
|
}
|
|
835
937
|
function agentsSelectingPiPackage(state, packageId) {
|
|
@@ -2103,6 +2205,7 @@ export function createChatWebApp(options = {}) {
|
|
|
2103
2205
|
reliabilityStore: createReliabilityStore(options.reliabilityStorePath),
|
|
2104
2206
|
traceCache: new Map(),
|
|
2105
2207
|
liveListeners: new Set(),
|
|
2208
|
+
userSkillManager: new UserSkillManager(process.cwd()),
|
|
2106
2209
|
};
|
|
2107
2210
|
const requireSession = (request, context) => context.requireSession({
|
|
2108
2211
|
request,
|
|
@@ -2115,6 +2218,7 @@ export function createChatWebApp(options = {}) {
|
|
|
2115
2218
|
const url = new URL(request.url);
|
|
2116
2219
|
ensureEventIndexing(state, context);
|
|
2117
2220
|
ensureCustomAgentProfiles(state, context);
|
|
2221
|
+
syncUserSkills(state, context);
|
|
2118
2222
|
const builtAsset = responseBuiltChatAsset(request, url.pathname);
|
|
2119
2223
|
if (builtAsset)
|
|
2120
2224
|
return builtAsset;
|
|
@@ -2162,9 +2266,10 @@ export function createChatWebApp(options = {}) {
|
|
|
2162
2266
|
rooms,
|
|
2163
2267
|
sessions,
|
|
2164
2268
|
agents: context.channelContext.getProfiles?.() ?? [],
|
|
2165
|
-
customAgents: state.agentStore.list(webSession.ownerScope, { includeArchived: true }),
|
|
2269
|
+
customAgents: serializeCustomAgents(state.agentStore.list(webSession.ownerScope, { includeArchived: true }), context),
|
|
2166
2270
|
modelDefaults: loadChatModelDefaults(process.cwd()),
|
|
2167
|
-
|
|
2271
|
+
modelCatalog: await loadModelCatalog(process.cwd()),
|
|
2272
|
+
agentCatalog: await buildAgentCatalog(context, state),
|
|
2168
2273
|
capabilities: {
|
|
2169
2274
|
actions: context.channelContext.getGatewayActions(),
|
|
2170
2275
|
},
|
|
@@ -2173,7 +2278,7 @@ export function createChatWebApp(options = {}) {
|
|
|
2173
2278
|
if (url.pathname === `${CHAT_WEB_API_PREFIX}/agent-catalog` && request.method === "GET") {
|
|
2174
2279
|
await requireSession(request, context);
|
|
2175
2280
|
return responseJson({
|
|
2176
|
-
catalog: await buildAgentCatalog(context),
|
|
2281
|
+
catalog: await buildAgentCatalog(context, state),
|
|
2177
2282
|
profiles: context.channelContext.getProfiles?.() ?? [],
|
|
2178
2283
|
});
|
|
2179
2284
|
}
|
|
@@ -2243,6 +2348,86 @@ export function createChatWebApp(options = {}) {
|
|
|
2243
2348
|
const removed = removePiPackage(piPackageId);
|
|
2244
2349
|
return responseJson({ removedPackage: removed });
|
|
2245
2350
|
}
|
|
2351
|
+
if (url.pathname === `${CHAT_WEB_API_PREFIX}/user-skills` && request.method === "GET") {
|
|
2352
|
+
await requireSession(request, context);
|
|
2353
|
+
return responseJson({ skills: state.userSkillManager.list() });
|
|
2354
|
+
}
|
|
2355
|
+
if (url.pathname === `${CHAT_WEB_API_PREFIX}/user-skills` && request.method === "POST") {
|
|
2356
|
+
requireSameOriginJsonRequest(request);
|
|
2357
|
+
await requireSession(request, context);
|
|
2358
|
+
const body = await readJsonBody(request);
|
|
2359
|
+
const name = normalizeUserSkillName(body.name);
|
|
2360
|
+
assertUserSkillNameIsAvailable(state, context, name);
|
|
2361
|
+
const skill = state.userSkillManager.create({
|
|
2362
|
+
name,
|
|
2363
|
+
description: normalizeUserSkillDescription(body.description ?? ""),
|
|
2364
|
+
markdown: normalizeUserSkillMarkdown(body.markdown ?? ""),
|
|
2365
|
+
});
|
|
2366
|
+
syncUserSkills(state, context);
|
|
2367
|
+
return responseJson({ skill }, { status: 201 });
|
|
2368
|
+
}
|
|
2369
|
+
if (url.pathname === `${CHAT_WEB_API_PREFIX}/user-skills/install` && request.method === "POST") {
|
|
2370
|
+
requireSameOriginJsonRequest(request);
|
|
2371
|
+
await requireSession(request, context);
|
|
2372
|
+
const body = await readJsonBody(request);
|
|
2373
|
+
const skill = await state.userSkillManager.installFromUrl(normalizeUserSkillUrl(body.url));
|
|
2374
|
+
try {
|
|
2375
|
+
assertUserSkillNameIsAvailable(state, context, skill.name, skill.id);
|
|
2376
|
+
}
|
|
2377
|
+
catch (error) {
|
|
2378
|
+
state.userSkillManager.remove(skill.id);
|
|
2379
|
+
throw error;
|
|
2380
|
+
}
|
|
2381
|
+
syncUserSkills(state, context);
|
|
2382
|
+
return responseJson({ skill }, { status: 201 });
|
|
2383
|
+
}
|
|
2384
|
+
const userSkillId = userSkillResourceId(url.pathname);
|
|
2385
|
+
if (userSkillId && request.method === "GET") {
|
|
2386
|
+
await requireSession(request, context);
|
|
2387
|
+
const skill = state.userSkillManager.get(userSkillId);
|
|
2388
|
+
if (!skill)
|
|
2389
|
+
throw new PiboWebHttpError("Skill not found", 404);
|
|
2390
|
+
const markdown = state.userSkillManager.getSkillMarkdown(skill.id);
|
|
2391
|
+
return responseJson({ skill, markdown });
|
|
2392
|
+
}
|
|
2393
|
+
if (userSkillId && request.method === "PATCH") {
|
|
2394
|
+
requireSameOriginJsonRequest(request);
|
|
2395
|
+
await requireSession(request, context);
|
|
2396
|
+
const existing = state.userSkillManager.get(userSkillId);
|
|
2397
|
+
if (!existing)
|
|
2398
|
+
throw new PiboWebHttpError("Skill not found", 404);
|
|
2399
|
+
const body = await readJsonBody(request);
|
|
2400
|
+
const input = {};
|
|
2401
|
+
if (body.name !== undefined)
|
|
2402
|
+
input.name = normalizeUserSkillName(body.name);
|
|
2403
|
+
if (body.description !== undefined)
|
|
2404
|
+
input.description = normalizeUserSkillDescription(body.description);
|
|
2405
|
+
if (body.markdown !== undefined)
|
|
2406
|
+
input.markdown = normalizeUserSkillMarkdown(body.markdown);
|
|
2407
|
+
if (body.enabled !== undefined)
|
|
2408
|
+
input.enabled = normalizeUserSkillEnabled(body.enabled);
|
|
2409
|
+
if (Object.keys(input).length === 0) {
|
|
2410
|
+
throw new PiboWebHttpError("No skill update fields provided", 400);
|
|
2411
|
+
}
|
|
2412
|
+
const nextName = input.name ?? existing.name;
|
|
2413
|
+
const nextEnabled = input.enabled ?? existing.enabled;
|
|
2414
|
+
if (nextEnabled) {
|
|
2415
|
+
assertUserSkillNameIsAvailable(state, context, nextName, existing.id);
|
|
2416
|
+
}
|
|
2417
|
+
const skill = state.userSkillManager.update(existing.id, input);
|
|
2418
|
+
syncUserSkills(state, context);
|
|
2419
|
+
return responseJson({ skill });
|
|
2420
|
+
}
|
|
2421
|
+
if (userSkillId && request.method === "DELETE") {
|
|
2422
|
+
requireSameOriginJsonRequest(request);
|
|
2423
|
+
await requireSession(request, context);
|
|
2424
|
+
const existing = state.userSkillManager.get(userSkillId);
|
|
2425
|
+
if (!existing)
|
|
2426
|
+
throw new PiboWebHttpError("Skill not found", 404);
|
|
2427
|
+
state.userSkillManager.remove(existing.id);
|
|
2428
|
+
syncUserSkills(state, context);
|
|
2429
|
+
return responseJson({ removedSkillId: existing.id });
|
|
2430
|
+
}
|
|
2246
2431
|
if (url.pathname === `${CHAT_WEB_API_PREFIX}/base-prompt` && request.method === "GET") {
|
|
2247
2432
|
await requireSession(request, context);
|
|
2248
2433
|
return responseJson({ basePrompt: await readPiboBasePrompt(process.cwd()) });
|
|
@@ -2286,7 +2471,7 @@ export function createChatWebApp(options = {}) {
|
|
|
2286
2471
|
if (url.pathname === `${CHAT_WEB_API_PREFIX}/agents` && request.method === "GET") {
|
|
2287
2472
|
const webSession = await requireSession(request, context);
|
|
2288
2473
|
const includeArchived = parseBooleanSearchParam(url, "includeArchived");
|
|
2289
|
-
return responseJson({ agents: state.agentStore.list(webSession.ownerScope, { includeArchived }) });
|
|
2474
|
+
return responseJson({ agents: serializeCustomAgents(state.agentStore.list(webSession.ownerScope, { includeArchived }), context) });
|
|
2290
2475
|
}
|
|
2291
2476
|
if (url.pathname === `${CHAT_WEB_API_PREFIX}/agents` && request.method === "POST") {
|
|
2292
2477
|
requireSameOriginJsonRequest(request);
|
|
@@ -2296,7 +2481,7 @@ export function createChatWebApp(options = {}) {
|
|
|
2296
2481
|
requireAgentProfileNameAvailable(state, context, input.displayName);
|
|
2297
2482
|
const agent = state.agentStore.create(input);
|
|
2298
2483
|
context.channelContext.upsertProfile?.(createCustomAgentProfileDefinition(agent));
|
|
2299
|
-
return responseJson({ agent }, { status: 201 });
|
|
2484
|
+
return responseJson({ agent: serializeCustomAgent(agent, context) }, { status: 201 });
|
|
2300
2485
|
}
|
|
2301
2486
|
const patchAgentId = agentResourceId(url.pathname);
|
|
2302
2487
|
if (patchAgentId && request.method === "PATCH") {
|
|
@@ -2320,7 +2505,7 @@ export function createChatWebApp(options = {}) {
|
|
|
2320
2505
|
else {
|
|
2321
2506
|
context.channelContext.upsertProfile?.(createCustomAgentProfileDefinition(owned));
|
|
2322
2507
|
}
|
|
2323
|
-
return responseJson({ agent: owned });
|
|
2508
|
+
return responseJson({ agent: serializeCustomAgent(owned, context) });
|
|
2324
2509
|
}
|
|
2325
2510
|
if (patchAgentId && request.method === "DELETE") {
|
|
2326
2511
|
requireSameOriginJsonRequest(request);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{N as e,P as t,U as n,o as r,r as i}from"./dist-SVPsM5Oi.js";import{n as a,r as o}from"./dist-tGfufz3b.js";import{r as s}from"./dist-
|
|
1
|
+
import{N as e,P as t,U as n,o as r,r as i}from"./dist-SVPsM5Oi.js";import{n as a,r as o}from"./dist-tGfufz3b.js";import{r as s}from"./dist-CUqpST5w.js";import{html as c}from"./dist-CqqUC8Ce.js";var l=1,u=33,d=34,f=35,p=36,m=new a(e=>{let t=e.pos;for(;;){if(e.next==10){e.advance();break}else if(e.next==123&&e.peek(1)==123||e.next<0)break;e.advance()}e.pos>t&&e.acceptToken(l)});function h(e,t,n){return new a(r=>{let i=r.pos;for(;r.next!=e&&r.next>=0&&(n||r.next!=38&&(r.next!=123||r.peek(1)!=123));)r.advance();r.pos>i&&r.acceptToken(t)})}var g=h(39,u,!1),_=h(34,d,!1),v=h(39,f,!0),y=h(34,p,!0),b=o.deserialize({version:14,states:"(jOVOqOOOeQpOOOvO!bO'#CaOOOP'#Cx'#CxQVOqOOO!OQpO'#CfO!WQpO'#ClO!]QpO'#CrO!bQpO'#CsOOQO'#Cv'#CvQ!gQpOOQ!lQpOOQ!qQpOOOOOV,58{,58{O!vOpO,58{OOOP-E6v-E6vO!{QpO,59QO#TQpO,59QOOQO,59W,59WO#YQpO,59^OOQO,59_,59_O#_QpOOO#_QpOOO#gQpOOOOOV1G.g1G.gO#oQpO'#CyO#tQpO1G.lOOQO1G.l1G.lO#|QpO1G.lOOQO1G.x1G.xO$UO`O'#DUO$ZOWO'#DUOOQO'#Co'#CoQOQpOOOOQO'#Cu'#CuO$`OtO'#CwO$qOrO'#CwOOQO,59e,59eOOQO-E6w-E6wOOQO7+$W7+$WO%SQpO7+$WO%[QpO7+$WOOOO'#Cp'#CpO%aOpO,59pOOOO'#Cq'#CqO%fOpO,59pOOOS'#Cz'#CzO%kOtO,59cOOQO,59c,59cOOOQ'#C{'#C{O%|OrO,59cO&_QpO<<GrOOQO<<Gr<<GrOOQO1G/[1G/[OOOS-E6x-E6xOOQO1G.}1G.}OOOQ-E6y-E6yOOQOAN=^AN=^",stateData:"&d~OvOS~OPROSQOVROWRO~OZTO[XO^VOaUOhWO~OR]OU^O~O[`O^aO~O[bO~O[cO~O[dO~ObeO~ObfO~ObgO~ORhO~O]kOwiO~O[lO~O_mO~OynOzoO~OysOztO~O[uO~O]wOwiO~O_yOwiO~OtzO~Os|O~OSQOV!OOW!OOr!OOy!QO~OSQOV!ROW!ROq!ROz!QO~O_!TOwiO~O]!UO~Oy!VO~Oz!VO~OSQOV!OOW!OOr!OOy!XO~OSQOV!ROW!ROq!ROz!XO~O]!ZO~O",goto:"#dyPPPPPzPPPP!WPPPPP!WPP!Z!^!a!d!dP!g!j!m!p!v#Q#WPPPPPPPP#^SROSS!Os!PT!Rt!SRYPRqeR{nR}oRZPRqfR[PRqgQSOR_SQj`SvjxRxlQ!PsR!W!PQ!StR!Y!SQpeRrf",nodeNames:`⚠ Text Content }} {{ Interpolation InterpolationContent Entity InvalidEntity Attribute BoundAttributeName [ Identifier ] ( ) ReferenceName # Is ExpressionAttributeValue AttributeInterpolation AttributeInterpolation EventName DirectiveName * StatementAttributeValue AttributeName AttributeValue`,maxTerm:42,nodeProps:[[`openedBy`,3,`{{`,15,`(`],[`closedBy`,4,`}}`,14,`)`],[`isolate`,-4,5,19,25,27,``]],skippedNodes:[0],repeatNodeCount:4,tokenData:"0r~RyOX#rXY$mYZ$mZ]#r]^$m^p#rpq$mqr#rrs%jst&Qtv#rvw&hwx)zxy*byz*xz{+`{}#r}!O+v!O!P-]!P!Q#r!Q![+v![!]+v!]!_#r!_!`-s!`!c#r!c!}+v!}#O.Z#O#P#r#P#Q.q#Q#R#r#R#S+v#S#T#r#T#o+v#o#p/X#p#q#r#q#r0Z#r%W#r%W;'S+v;'S;:j-V;:j;=`$g<%lO+vQ#wTUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rQ$ZSO#q#r#r;'S#r;'S;=`$g<%lO#rQ$jP;=`<%l#rR$t[UQvPOX#rXY$mYZ$mZ]#r]^$m^p#rpq$mq#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR%qTyPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR&XTaPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR&oXUQWPOp'[pq#rq!]'[!]!^#r!^#q'[#q#r(d#r;'S'[;'S;=`)t<%lO'[R'aXUQOp'[pq#rq!]'[!]!^'|!^#q'[#q#r(d#r;'S'[;'S;=`)t<%lO'[R(TTVPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR(gXOp'[pq#rq!]'[!]!^'|!^#q'[#q#r)S#r;'S'[;'S;=`)t<%lO'[P)VUOp)Sq!])S!]!^)i!^;'S)S;'S;=`)n<%lO)SP)nOVPP)qP;=`<%l)SR)wP;=`<%l'[R*RTzPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR*iT^PUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR+PT_PUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR+gThPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR+}b[PUQO}#r}!O+v!O!Q#r!Q![+v![!]+v!]!c#r!c!}+v!}#R#r#R#S+v#S#T#r#T#o+v#o#q#r#q#r$W#r%W#r%W;'S+v;'S;:j-V;:j;=`$g<%lO+vR-YP;=`<%l+vR-dTwPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR-zTUQbPO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR.bTZPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR.xT]PUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR/^VUQO#o#r#o#p/s#p#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#rR/zTSPUQO#q#r#q#r$W#r;'S#r;'S;=`$g<%lO#r~0^TO#q#r#q#r0m#r;'S#r;'S;=`$g<%lO#r~0rOR~",tokenizers:[m,g,_,v,y,0,1],topRules:{Content:[0,2],Attribute:[1,9]},tokenPrec:0}),x=s.parser.configure({top:`SingleExpression`}),S=b.configure({props:[e({Text:t.content,Is:t.definitionOperator,AttributeName:t.attributeName,"AttributeValue ExpressionAttributeValue StatementAttributeValue":t.attributeValue,Entity:t.character,InvalidEntity:t.invalid,"BoundAttributeName/Identifier":t.attributeName,"EventName/Identifier":t.special(t.attributeName),"ReferenceName/Identifier":t.variableName,"DirectiveName/Identifier":t.keyword,"{{ }}":t.brace,"( )":t.paren,"[ ]":t.bracket,"# '*'":t.punctuation})]}),C={parser:x},w={parser:s.parser},T=S.configure({wrap:n((e,t)=>e.name==`InterpolationContent`?C:null)}),E=S.configure({wrap:n((e,t)=>e.name==`InterpolationContent`?C:e.name==`AttributeInterpolation`?e.node.parent?.name==`StatementAttributeValue`?w:C:null),top:`Attribute`}),D={parser:T},O={parser:E},k=c({selfClosingTags:!0});function A(e){return e.configure({wrap:n(M)},`angular`)}var j=A(k.language);function M(e,t){switch(e.name){case`Attribute`:return/^[*#(\[]|\{\{/.test(t.read(e.from,e.to))?O:null;case`Text`:return D}return null}function N(e={}){let t=k;if(e.base){if(e.base.language.name!=`html`||!(e.base.language instanceof i))throw RangeError(`The base option must be the result of calling html(...)`);t=e.base}return new r(t.language==k.language?j:A(t.language),[t.support,t.language.data.of({closeBrackets:{brackets:[`[`,`{`,`"`]},indentOnInput:/^\s*[\}\]]$/})])}export{N as angular};
|