@tplog/pi-zendy 0.4.0 → 0.4.1
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 +4 -1
- package/dist/config/schema.d.ts +8 -0
- package/dist/config/schema.js +32 -0
- package/dist/config/store.d.ts +1 -1
- package/dist/config/store.js +5 -0
- package/extensions/commands.ts +7 -0
- package/extensions/tools.ts +17 -5
- package/package.json +1 -1
- package/skills/zendy/SKILL.md +4 -2
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ zendy is a single pi extension that provides:
|
|
|
14
14
|
- **Slash Commands** — `/zendy-config` to set up credentials, `/zendy-status` to check connectivity.
|
|
15
15
|
- **Skill** — a `zendy` skill (also `/skill:zendy`) that teaches the agent the ticket-analysis workflow, so "analyze ticket #1959" reliably uses the right tools in the right order.
|
|
16
16
|
- **Session Safety** — Automatic workspace isolation and cleanup for source code analysis.
|
|
17
|
+
- **Source Registry** — Bundled Dify source repository defaults. Enterprise repos use SSH URLs, so GitHub SSH permissions remain the access gate.
|
|
17
18
|
|
|
18
19
|
Typical workflow:
|
|
19
20
|
|
|
@@ -73,7 +74,7 @@ The agent can call these tools directly:
|
|
|
73
74
|
| `zendy_whoami` | Check the currently authenticated Zendesk identity |
|
|
74
75
|
| `zendy_helm_get` | Query Helm chart values, images, validation by version |
|
|
75
76
|
| `zendy_kg_search` | Semantic search over historical tickets |
|
|
76
|
-
| `zendy_source_status` | Check source analysis workspace |
|
|
77
|
+
| `zendy_source_status` | Check source analysis workspace and bundled Dify source repository registry |
|
|
77
78
|
|
|
78
79
|
## How it works
|
|
79
80
|
|
|
@@ -81,3 +82,5 @@ zendy registers as a pi extension package. The extension provides tools (callabl
|
|
|
81
82
|
slash commands (for human engineers), and session lifecycle hooks (workspace creation, cleanup).
|
|
82
83
|
All data access goes through direct REST APIs — no `zcli`, `zendesk-kg`, or other CLI tools
|
|
83
84
|
are required at runtime.
|
|
85
|
+
|
|
86
|
+
For source analysis, zendy ships default repository entries for Dify Enterprise backend/frontend and related public Dify repositories. The Enterprise entries are SSH URLs; users without GitHub SSH access can install zendy, but source clone attempts will fail at Git authentication.
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface ZendyConfig {
|
|
2
2
|
zendesk?: ZendeskConfig;
|
|
3
3
|
zendeskKg?: ZendeskKgConfig;
|
|
4
|
+
sourceRepos?: Record<string, SourceRepoConfig>;
|
|
4
5
|
}
|
|
5
6
|
export interface ZendeskConfig {
|
|
6
7
|
subdomain?: string;
|
|
@@ -11,4 +12,11 @@ export interface ZendeskKgConfig {
|
|
|
11
12
|
apiUrl?: string;
|
|
12
13
|
apiKey?: string;
|
|
13
14
|
}
|
|
15
|
+
export interface SourceRepoConfig {
|
|
16
|
+
url: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
visibility?: "private" | "public";
|
|
19
|
+
area?: "backend" | "frontend" | "oss" | "plugin" | "sandbox";
|
|
20
|
+
}
|
|
14
21
|
export declare const DEFAULT_KG_API_URL = "https://zendesk-ticket-retriever.vercel.app";
|
|
22
|
+
export declare const DEFAULT_SOURCE_REPOS: Record<string, SourceRepoConfig>;
|
package/dist/config/schema.js
CHANGED
|
@@ -1,2 +1,34 @@
|
|
|
1
1
|
// Config schema and types for zendy configuration (~/.zendy/config.json).
|
|
2
2
|
export const DEFAULT_KG_API_URL = "https://zendesk-ticket-retriever.vercel.app";
|
|
3
|
+
export const DEFAULT_SOURCE_REPOS = {
|
|
4
|
+
enterpriseBackend: {
|
|
5
|
+
url: "git@github.com:langgenius/dify-enterprise.git",
|
|
6
|
+
description: "Dify Enterprise backend code",
|
|
7
|
+
visibility: "private",
|
|
8
|
+
area: "backend",
|
|
9
|
+
},
|
|
10
|
+
enterpriseFrontend: {
|
|
11
|
+
url: "git@github.com:langgenius/dify-enterprise-frontend.git",
|
|
12
|
+
description: "Dify Enterprise frontend code",
|
|
13
|
+
visibility: "private",
|
|
14
|
+
area: "frontend",
|
|
15
|
+
},
|
|
16
|
+
difyOss: {
|
|
17
|
+
url: "https://github.com/langgenius/dify.git",
|
|
18
|
+
description: "Open-source Dify repository",
|
|
19
|
+
visibility: "public",
|
|
20
|
+
area: "oss",
|
|
21
|
+
},
|
|
22
|
+
pluginDaemon: {
|
|
23
|
+
url: "https://github.com/langgenius/dify-plugin-daemon.git",
|
|
24
|
+
description: "Dify plugin daemon",
|
|
25
|
+
visibility: "public",
|
|
26
|
+
area: "plugin",
|
|
27
|
+
},
|
|
28
|
+
sandbox: {
|
|
29
|
+
url: "https://github.com/langgenius/dify-sandbox.git",
|
|
30
|
+
description: "Dify sandbox",
|
|
31
|
+
visibility: "public",
|
|
32
|
+
area: "sandbox",
|
|
33
|
+
},
|
|
34
|
+
};
|
package/dist/config/store.d.ts
CHANGED
package/dist/config/store.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
|
+
import { DEFAULT_SOURCE_REPOS } from "./schema.js";
|
|
6
7
|
const CONFIG_DIR = join(homedir(), ".zendy");
|
|
7
8
|
const CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
8
9
|
// ── Env overrides ─────────────────────────────────────────────────────
|
|
@@ -52,6 +53,10 @@ export function getConfig() {
|
|
|
52
53
|
...fileConfig.zendeskKg,
|
|
53
54
|
...envK,
|
|
54
55
|
},
|
|
56
|
+
sourceRepos: {
|
|
57
|
+
...DEFAULT_SOURCE_REPOS,
|
|
58
|
+
...fileConfig.sourceRepos,
|
|
59
|
+
},
|
|
55
60
|
};
|
|
56
61
|
}
|
|
57
62
|
export function writeConfig(config) {
|
package/extensions/commands.ts
CHANGED
|
@@ -66,6 +66,9 @@ async function configCommand(_args: string, ctx: {
|
|
|
66
66
|
lines.push(
|
|
67
67
|
`KG: ${c.zendeskKg?.apiKey ? `apiKey=*** (set), apiUrl=${c.zendeskKg.apiUrl || "default"}` : "not configured"}`,
|
|
68
68
|
);
|
|
69
|
+
const repoEntries = Object.entries(c.sourceRepos ?? {});
|
|
70
|
+
const privateCount = repoEntries.filter(([, repo]) => repo.visibility === "private").length;
|
|
71
|
+
lines.push(`Source repos: ${repoEntries.length} configured (${privateCount} private SSH-gated)`);
|
|
69
72
|
ctx.ui.notify(`[zendy-config]\n${lines.join("\n")}`, "info");
|
|
70
73
|
}
|
|
71
74
|
}
|
|
@@ -105,6 +108,10 @@ async function statusCommand(_args: string, ctx: {
|
|
|
105
108
|
srcDir ? ` ✓ Source workspace — ${srcDir}` : " - Source workspace — not active (will be created on session start)",
|
|
106
109
|
);
|
|
107
110
|
|
|
111
|
+
const repoEntries = Object.entries(getConfig().sourceRepos ?? {});
|
|
112
|
+
const privateCount = repoEntries.filter(([, repo]) => repo.visibility === "private").length;
|
|
113
|
+
lines.push(` ✓ Source repos — ${repoEntries.length} configured (${privateCount} private SSH-gated)`);
|
|
114
|
+
|
|
108
115
|
ctx.ui.notify(`Zendy Status:\n${lines.join("\n")}`, hasIssue ? "error" : "info");
|
|
109
116
|
}
|
|
110
117
|
|
package/extensions/tools.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Type } from "typebox";
|
|
|
6
6
|
import * as zendesk from "../dist/clients/zendesk.js";
|
|
7
7
|
import * as helm from "../dist/clients/helm-watchdog.js";
|
|
8
8
|
import * as kg from "../dist/clients/zendesk-kg.js";
|
|
9
|
+
import { getConfig } from "../dist/config/store.js";
|
|
9
10
|
|
|
10
11
|
// IMPORTANT: only `content` is sent to the model; `details` is UI/extension
|
|
11
12
|
// metadata the model never sees (verified empirically against pi 0.79). Any
|
|
@@ -248,15 +249,26 @@ function registerSourceTools(pi: ExtensionAPI): void {
|
|
|
248
249
|
pi.registerTool({
|
|
249
250
|
name: "zendy_source_status",
|
|
250
251
|
label: "Zendy Source Status",
|
|
251
|
-
description: "Report the zendy source-analysis workspace path and
|
|
252
|
-
promptSnippet: "Check source workspace
|
|
252
|
+
description: "Report the zendy source-analysis workspace path, bundled source repositories, and source-cloning authorization rules.",
|
|
253
|
+
promptSnippet: "Check source workspace and repo registry with zendy_source_status.",
|
|
253
254
|
parameters: Type.Object({}),
|
|
254
255
|
async execute() {
|
|
255
256
|
const workspace = process.env["ZENDY_SRC_DIR"] ?? null;
|
|
256
|
-
const
|
|
257
|
+
const repos = getConfig().sourceRepos ?? {};
|
|
258
|
+
const repoLines = Object.entries(repos).map(([name, repo]) => {
|
|
259
|
+
const visibility = repo.visibility ?? "public";
|
|
260
|
+
const access = visibility === "private" ? "SSH access required" : "public";
|
|
261
|
+
return `- ${name}: ${repo.url} (${access})${repo.description ? ` — ${repo.description}` : ""}`;
|
|
262
|
+
});
|
|
263
|
+
const note = "Source cloning/search requires explicit user permission per zendy workflow rules. Private Enterprise repos are SSH-gated; clone failures usually mean the user lacks GitHub access.";
|
|
257
264
|
return textResult(
|
|
258
|
-
|
|
259
|
-
|
|
265
|
+
[
|
|
266
|
+
`Source workspace: ${workspace ?? "(not active — created on session start)"}`,
|
|
267
|
+
"Configured source repositories:",
|
|
268
|
+
repoLines.length ? repoLines.join("\n") : "- (none configured)",
|
|
269
|
+
note,
|
|
270
|
+
].join("\n"),
|
|
271
|
+
{ workspace, repos, note },
|
|
260
272
|
);
|
|
261
273
|
},
|
|
262
274
|
});
|
package/package.json
CHANGED
package/skills/zendy/SKILL.md
CHANGED
|
@@ -25,7 +25,7 @@ support engineer can analyze a ticket end-to-end without leaving the terminal.
|
|
|
25
25
|
| `zendy_whoami` | Verify which Zendesk account is authenticated |
|
|
26
26
|
| `zendy_helm_get` | Dify Helm chart data by exact version: values.yaml, images, validation, latest |
|
|
27
27
|
| `zendy_kg_search` | Semantic search over historical tickets; returns ticketIds |
|
|
28
|
-
| `zendy_source_status` | Check the source-analysis workspace
|
|
28
|
+
| `zendy_source_status` | Check the source-analysis workspace, bundled repo registry, and authorization rules |
|
|
29
29
|
|
|
30
30
|
Use these tools for all data access. Do not use zcli, curl, or any external Zendesk
|
|
31
31
|
CLI. If credentials are missing, tell the user to run `/zendy-config`; check
|
|
@@ -55,6 +55,8 @@ connectivity with `/zendy-status`.
|
|
|
55
55
|
- **Source code analysis requires explicit user permission.** If config-level
|
|
56
56
|
analysis cannot settle the question, ask the user whether to check the source
|
|
57
57
|
(e.g. "需要我去源码确认吗?") — never clone without permission. Use
|
|
58
|
-
`zendy_source_status` to find the workspace.
|
|
58
|
+
`zendy_source_status` to find the workspace and bundled source repo URLs.
|
|
59
|
+
Enterprise backend/frontend repos are SSH-gated; if cloning fails, ask the user
|
|
60
|
+
to confirm their GitHub SSH access rather than trying alternate credentials.
|
|
59
61
|
- **Inspect before filtering.** On the first call to an unfamiliar response shape,
|
|
60
62
|
look at the structure before writing filter expressions; never assume field names.
|