@pasko70/pibo 1.7.7 → 1.7.9

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.
Files changed (39) hide show
  1. package/dist/apps/chat/chat-user-skill-routes.js +51 -19
  2. package/dist/apps/chat/model-catalog.js +2 -0
  3. package/dist/apps/chat/web-app.js +2 -2
  4. package/dist/apps/chat-ui/assets/{dist-BhCflw5L.js → dist-BLQTYmgi.js} +1 -1
  5. package/dist/apps/chat-ui/assets/{dist-C2wdpulS.js → dist-BLYDOjGT.js} +1 -1
  6. package/dist/apps/chat-ui/assets/{dist-BUfawaFa.js → dist-Bg2k47fY.js} +1 -1
  7. package/dist/apps/chat-ui/assets/{dist-iblHo9vw.js → dist-Bv912fTl.js} +1 -1
  8. package/dist/apps/chat-ui/assets/{dist-NDLYTRqO.js → dist-CCOZbHCt.js} +1 -1
  9. package/dist/apps/chat-ui/assets/{dist-ChMCJ0Xh.js → dist-D6ImmtZ3.js} +1 -1
  10. package/dist/apps/chat-ui/assets/{dist-C5S2MWeq.js → dist-DDQWCHTh.js} +1 -1
  11. package/dist/apps/chat-ui/assets/{dist-XR2wwVeo.js → dist-DTJJ5-iA.js} +1 -1
  12. package/dist/apps/chat-ui/assets/{dist-COMZszUx.js → dist-Daom6uMW.js} +1 -1
  13. package/dist/apps/chat-ui/assets/{dist-CqZsX_X9.js → dist-Dgs6LwMW.js} +1 -1
  14. package/dist/apps/chat-ui/assets/{dist-CJOnkhP1.js → dist-LRUZKp77.js} +1 -1
  15. package/dist/apps/chat-ui/assets/index-BnZ0V5cJ.js +173 -0
  16. package/dist/apps/chat-ui/assets/index-DbRZGRDd.css +1 -0
  17. package/dist/apps/chat-ui/index.html +2 -2
  18. package/dist/apps/chat-vscode-web/assets/index-CiQZTRZH.js +41 -0
  19. package/dist/apps/chat-vscode-web/index.html +1 -1
  20. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  21. package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.7.9.vsix +0 -0
  22. package/dist/cli.js +12 -3
  23. package/dist/core/context-guard.js +126 -0
  24. package/dist/core/gateway-resource-guard.js +215 -0
  25. package/dist/core/routed-session.js +76 -1
  26. package/dist/core/runtime.js +40 -2
  27. package/dist/core/session-router.js +2 -0
  28. package/dist/debug/index.js +40 -0
  29. package/dist/mcp/output.js +19 -4
  30. package/dist/providers/openai-gpt56.js +153 -0
  31. package/dist/ralph/cli.js +49 -5
  32. package/dist/session-ui/terminalRows.js +59 -0
  33. package/dist/skills/cli.js +33 -23
  34. package/dist/tools/guides.js +17 -0
  35. package/dist/user-skills/manager.js +106 -8
  36. package/package.json +1 -1
  37. package/dist/apps/chat-ui/assets/index-BStUapSa.css +0 -1
  38. package/dist/apps/chat-ui/assets/index-BYqOi32B.js +0 -173
  39. package/dist/apps/chat-vscode-web/assets/index-B4Jk2P5o.js +0 -41
@@ -1,3 +1,4 @@
1
+ import { normalizeUserSkillScope, normalizeWritableUserSkillScope } from "../../user-skills/manager.js";
1
2
  import { PiboWebHttpError, readJsonBody, responseJson } from "../../web/http.js";
2
3
  import { CHAT_WEB_API_PREFIX, userSkillResourceId } from "./chat-api-routes.js";
3
4
  import { normalizeUserSkillDescription, normalizeUserSkillEnabled, normalizeUserSkillMarkdown, normalizeUserSkillName, normalizeUserSkillUrl, } from "./chat-request-normalizers.js";
@@ -26,13 +27,19 @@ export function syncChatUserSkills(options) {
26
27
  const unregisterSkill = channelContext.unregisterSkill;
27
28
  if (!registerSkill || !unregisterSkill)
28
29
  return;
29
- const userSkills = userSkillManager.list();
30
+ const userSkills = userSkillManager.list("all");
30
31
  const catalogSkills = channelContext.getCapabilityCatalog?.().skills ?? [];
31
32
  const catalogSkillByName = new Map(catalogSkills.map((skill) => [skill.name, skill]));
32
33
  const reservedSkillNames = new Set(catalogSkills.filter((skill) => skill.kind !== "user").map((skill) => skill.name));
33
- const enabledNames = new Set(userSkills
34
- .filter((skill) => skill.enabled && !reservedSkillNames.has(skill.name))
35
- .map((skill) => skill.name));
34
+ const enabledSkillByName = new Map();
35
+ for (const skill of userSkills) {
36
+ if (!skill.enabled || reservedSkillNames.has(skill.name))
37
+ continue;
38
+ const existing = enabledSkillByName.get(skill.name);
39
+ if (!existing || skill.scope === "workspace")
40
+ enabledSkillByName.set(skill.name, skill);
41
+ }
42
+ const enabledNames = new Set(enabledSkillByName.keys());
36
43
  const syncedNames = previouslySyncedNames ?? new Set();
37
44
  // Unregister disabled, removed, or now built-in user skills. Avoid removing a
38
45
  // built-in/plugin skill if a promoted user skill has the same name.
@@ -43,10 +50,16 @@ export function syncChatUserSkills(options) {
43
50
  unregisterSkill(name);
44
51
  }
45
52
  }
46
- // Register only newly enabled user skills. Re-registering an already synced
47
- // skill would trip the registry duplicate-skill guard and break the web UI.
48
- for (const skill of userSkills) {
49
- if (skill.enabled && !reservedSkillNames.has(skill.name) && !syncedNames.has(skill.name)) {
53
+ // Register the winning enabled skill per name. Workspace-local skills take
54
+ // precedence over global user skills with the same name; if the winning path
55
+ // changes, re-register the user skill so runtime context loads the right body.
56
+ for (const skill of enabledSkillByName.values()) {
57
+ const catalogSkill = catalogSkillByName.get(skill.name);
58
+ if (catalogSkill?.kind === "user" && catalogSkill.path !== skill.path) {
59
+ unregisterSkill(skill.name);
60
+ registerSkill({ name: skill.name, path: skill.path, enabled: true, kind: "user" });
61
+ }
62
+ else if (!syncedNames.has(skill.name)) {
50
63
  registerSkill({ name: skill.name, path: skill.path, enabled: true, kind: "user" });
51
64
  }
52
65
  }
@@ -55,7 +68,7 @@ export function syncChatUserSkills(options) {
55
68
  function assertUserSkillNameIsAvailable(options) {
56
69
  const { userSkillManager, channelContext, name, currentSkillId } = options;
57
70
  const currentSkill = currentSkillId ? userSkillManager.get(currentSkillId) : undefined;
58
- const conflict = (channelContext.getCapabilityCatalog?.().skills ?? []).find((skill) => (skill.name === name && (!currentSkill || currentSkill.name !== name)));
71
+ const conflict = (channelContext.getCapabilityCatalog?.().skills ?? []).find((skill) => (skill.name === name && skill.kind !== "user" && (!currentSkill || currentSkill.name !== name)));
59
72
  if (conflict) {
60
73
  throw new PiboWebHttpError(`Skill name "${name}" conflicts with an existing registered skill`, 409);
61
74
  }
@@ -69,45 +82,63 @@ function syncAndInvalidate(options) {
69
82
  });
70
83
  options.invalidateBootstrapCatalogCache();
71
84
  }
85
+ function requestScope(request, fallback = "all") {
86
+ return normalizeUserSkillScope(new URL(request.url).searchParams.get("scope") ?? undefined, fallback);
87
+ }
88
+ function bodyScope(body, fallback = "global") {
89
+ if (body.scope !== undefined && typeof body.scope !== "string") {
90
+ throw new PiboWebHttpError("Skill scope must be a string", 400);
91
+ }
92
+ try {
93
+ return normalizeWritableUserSkillScope(body.scope, fallback);
94
+ }
95
+ catch (error) {
96
+ throw new PiboWebHttpError(error instanceof Error ? error.message : String(error), 400);
97
+ }
98
+ }
72
99
  export async function handleChatUserSkillRoute(options) {
73
100
  const { route, request, userSkillManager, channelContext } = options;
74
101
  switch (route.kind) {
75
102
  case "user-skills-list":
76
- return responseJson({ skills: userSkillManager.list() });
103
+ return responseJson({ skills: userSkillManager.list(requestScope(request)) });
77
104
  case "user-skills-create": {
78
105
  const body = await readJsonBody(request);
106
+ const scope = bodyScope(body);
79
107
  const name = normalizeUserSkillName(body.name);
80
108
  assertUserSkillNameIsAvailable({ userSkillManager, channelContext, name });
81
109
  const skill = userSkillManager.create({
82
110
  name,
83
111
  description: normalizeUserSkillDescription(body.description ?? ""),
84
112
  markdown: normalizeUserSkillMarkdown(body.markdown ?? ""),
85
- });
113
+ }, scope);
86
114
  syncAndInvalidate(options);
87
115
  return responseJson({ skill }, { status: 201 });
88
116
  }
89
117
  case "user-skills-install": {
90
118
  const body = await readJsonBody(request);
91
- const skill = await userSkillManager.installFromUrl(normalizeUserSkillUrl(body.url));
119
+ const scope = bodyScope(body);
120
+ const skill = await userSkillManager.installFromUrl(normalizeUserSkillUrl(body.url), scope);
92
121
  try {
93
122
  assertUserSkillNameIsAvailable({ userSkillManager, channelContext, name: skill.name, currentSkillId: skill.id });
94
123
  }
95
124
  catch (error) {
96
- userSkillManager.remove(skill.id);
125
+ userSkillManager.remove(skill.id, scope);
97
126
  throw error;
98
127
  }
99
128
  syncAndInvalidate(options);
100
129
  return responseJson({ skill }, { status: 201 });
101
130
  }
102
131
  case "user-skill-read": {
103
- const skill = userSkillManager.get(route.skillId);
132
+ const scope = requestScope(request);
133
+ const skill = userSkillManager.get(route.skillId, scope);
104
134
  if (!skill)
105
135
  throw new PiboWebHttpError("Skill not found", 404);
106
- const markdown = userSkillManager.getSkillMarkdown(skill.id);
136
+ const markdown = userSkillManager.getSkillMarkdown(skill.id, scope);
107
137
  return responseJson({ skill, markdown });
108
138
  }
109
139
  case "user-skill-update": {
110
- const existing = userSkillManager.get(route.skillId);
140
+ const scope = requestScope(request);
141
+ const existing = userSkillManager.get(route.skillId, scope);
111
142
  if (!existing)
112
143
  throw new PiboWebHttpError("Skill not found", 404);
113
144
  const body = await readJsonBody(request);
@@ -133,15 +164,16 @@ export async function handleChatUserSkillRoute(options) {
133
164
  currentSkillId: existing.id,
134
165
  });
135
166
  }
136
- const skill = userSkillManager.update(existing.id, input);
167
+ const skill = userSkillManager.update(existing.id, input, scope);
137
168
  syncAndInvalidate(options);
138
169
  return responseJson({ skill });
139
170
  }
140
171
  case "user-skill-delete": {
141
- const existing = userSkillManager.get(route.skillId);
172
+ const scope = requestScope(request);
173
+ const existing = userSkillManager.get(route.skillId, scope);
142
174
  if (!existing)
143
175
  throw new PiboWebHttpError("Skill not found", 404);
144
- userSkillManager.remove(existing.id);
176
+ userSkillManager.remove(existing.id, scope);
145
177
  syncAndInvalidate(options);
146
178
  return responseJson({ removedSkillId: existing.id });
147
179
  }
@@ -1,6 +1,7 @@
1
1
  import { createAgentSessionServices } from "@mariozechner/pi-coding-agent";
2
2
  import { registerMiniMaxProvider } from "../../providers/minimax.js";
3
3
  import { registerGlmProvider } from "../../providers/glm.js";
4
+ import { registerOpenAiGpt56Models } from "../../providers/openai-gpt56.js";
4
5
  export function buildModelCatalogFromRegistry(registry) {
5
6
  const providers = new Map();
6
7
  for (const model of registry.getAll()) {
@@ -45,6 +46,7 @@ export async function loadModelCatalogWithServices(createServices, cwd = process
45
46
  }
46
47
  export async function loadModelCatalog(cwd = process.cwd()) {
47
48
  return loadModelCatalogWithServices(createAgentSessionServices, cwd, (registry) => {
49
+ registerOpenAiGpt56Models(registry);
48
50
  registerMiniMaxProvider(registry);
49
51
  registerGlmProvider(registry);
50
52
  });
@@ -22,7 +22,7 @@ import { createDefaultPiboReliabilityStore, PiboReliabilityStore } from "../../r
22
22
  import { listMcpServerInfos } from "../../mcp/agent-context.js";
23
23
  import { getDefaultPiboWorkspace } from "../../core/workspace.js";
24
24
  import { findPiPackage, listPiPackages } from "../../pi-packages/store.js";
25
- import { UserSkillManager } from "../../user-skills/manager.js";
25
+ import { ScopedUserSkillManager } from "../../user-skills/manager.js";
26
26
  import { ChatDataIngestService } from "../../data/ingest-service.js";
27
27
  import { ChatEventCommandService } from "./data/event-command-service.js";
28
28
  import { ChatReadStateService } from "./data/read-state-service.js";
@@ -3029,7 +3029,7 @@ export function createChatWebApp(options = {}) {
3029
3029
  persistenceMetrics: createPersistenceMetrics(),
3030
3030
  resourceMetrics: createResourceMetrics(),
3031
3031
  eventLoopDelay,
3032
- userSkillManager: new UserSkillManager(os.homedir()),
3032
+ userSkillManager: new ScopedUserSkillManager({ globalRoot: os.homedir(), workspaceRoot: process.cwd() }),
3033
3033
  workflowDraftStore: new ChatWorkflowDraftStore(dataStore),
3034
3034
  workflowPublishedVersionStore: new ChatWorkflowPublishedVersionStore(dataStore),
3035
3035
  workflowArchiveStore: new ChatWorkflowArchiveStore(dataStore),