@tplog/pi-zendy 0.2.17 → 0.3.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 +52 -22
- package/dist/clients/helm-watchdog.d.ts +7 -0
- package/dist/clients/helm-watchdog.js +49 -0
- package/dist/clients/zendesk-kg.d.ts +59 -0
- package/dist/clients/zendesk-kg.js +100 -0
- package/dist/clients/zendesk.d.ts +64 -0
- package/dist/clients/zendesk.js +90 -0
- package/dist/config/migrate.d.ts +6 -0
- package/dist/config/migrate.js +78 -0
- package/dist/config/schema.d.ts +14 -0
- package/dist/config/schema.js +2 -0
- package/dist/config/store.d.ts +7 -0
- package/dist/config/store.js +81 -0
- package/dist/index.js +4 -44
- package/dist/preflight.js +101 -24
- package/extensions/commands.ts +164 -0
- package/extensions/tools.ts +190 -0
- package/extensions/zendy.ts +140 -0
- package/package.json +3 -9
- package/agents.md +0 -118
- package/extensions/custom-header.ts +0 -49
- package/extensions/source-cleanup.ts +0 -162
- package/extensions/status.ts +0 -82
- package/extensions/zendy-context.ts +0 -24
- package/skills/helm-watchdog/SKILL.md +0 -146
- package/skills/source-check/SKILL.md +0 -143
- package/skills/zendesk-cli/SKILL.md +0 -37
- package/skills/zendesk-kg/SKILL.md +0 -120
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Source-clone cleanup extension (deterministic, code-level defense).
|
|
3
|
-
*
|
|
4
|
-
* dify-enterprise / dify-enterprise-frontend are PRIVATE repositories.
|
|
5
|
-
* Relying on skill-level ("please remember to clean up") guidance is
|
|
6
|
-
* prompt-level defense — an AI can forget. This extension enforces
|
|
7
|
-
* cleanup in code:
|
|
8
|
-
*
|
|
9
|
-
* - on session_start:
|
|
10
|
-
* · create /tmp/zendy-session-<pid>-<ts>/ (mode 0700)
|
|
11
|
-
* · export its path via process.env.ZENDY_SRC_DIR so bash
|
|
12
|
-
* subprocesses spawned by pi (and the source-check skill)
|
|
13
|
-
* clone into it
|
|
14
|
-
* · sweep orphan session dirs whose owning pid is dead
|
|
15
|
-
*
|
|
16
|
-
* - on session_shutdown AND on process exit / SIGINT / SIGTERM /
|
|
17
|
-
* uncaughtException:
|
|
18
|
-
* · rm -rf this session's dir (idempotent, best-effort)
|
|
19
|
-
*
|
|
20
|
-
* - /cleanup-src slash command inside pi: wipe all dify-* and
|
|
21
|
-
* orphan zendy-session-* dirs on demand.
|
|
22
|
-
*
|
|
23
|
-
* Caveats (do not oversell):
|
|
24
|
-
* - kill -9 / OOM / power loss bypass handlers → rely on the
|
|
25
|
-
* next startup's orphan sweep.
|
|
26
|
-
* - rm -rf is not secure erase. For at-rest confidentiality,
|
|
27
|
-
* disk encryption (FileVault/LUKS) is required.
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
31
|
-
import { mkdirSync, rmSync, readdirSync } from "node:fs";
|
|
32
|
-
import { join } from "node:path";
|
|
33
|
-
|
|
34
|
-
const BASE_DIR = "/tmp";
|
|
35
|
-
const SESSION_PREFIX = "zendy-session-";
|
|
36
|
-
const WIPE_PREFIXES = ["dify-", SESSION_PREFIX];
|
|
37
|
-
|
|
38
|
-
function parseSessionDir(name: string): { pid: number } | null {
|
|
39
|
-
const m = /^zendy-session-(\d+)-(\d+)$/.exec(name);
|
|
40
|
-
return m ? { pid: parseInt(m[1]!, 10) } : null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function isAlive(pid: number): boolean {
|
|
44
|
-
try {
|
|
45
|
-
process.kill(pid, 0);
|
|
46
|
-
return true;
|
|
47
|
-
} catch (e) {
|
|
48
|
-
return (e as NodeJS.ErrnoException).code === "EPERM";
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function safeRmrf(path: string): boolean {
|
|
53
|
-
try {
|
|
54
|
-
rmSync(path, { recursive: true, force: true });
|
|
55
|
-
return true;
|
|
56
|
-
} catch {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function sweepOrphans(base: string, exclude: string): string[] {
|
|
62
|
-
let entries;
|
|
63
|
-
try {
|
|
64
|
-
entries = readdirSync(base, { withFileTypes: true });
|
|
65
|
-
} catch {
|
|
66
|
-
return [];
|
|
67
|
-
}
|
|
68
|
-
const removed: string[] = [];
|
|
69
|
-
for (const e of entries) {
|
|
70
|
-
if (!e.isDirectory()) continue;
|
|
71
|
-
const info = parseSessionDir(e.name);
|
|
72
|
-
if (!info) continue;
|
|
73
|
-
const full = join(base, e.name);
|
|
74
|
-
if (full === exclude) continue;
|
|
75
|
-
if (isAlive(info.pid)) continue;
|
|
76
|
-
if (safeRmrf(full)) removed.push(full);
|
|
77
|
-
}
|
|
78
|
-
return removed;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export default function (pi: ExtensionAPI) {
|
|
82
|
-
const ts = Date.now();
|
|
83
|
-
const sessionDir = join(BASE_DIR, `${SESSION_PREFIX}${process.pid}-${ts}`);
|
|
84
|
-
let cleanedUp = false;
|
|
85
|
-
|
|
86
|
-
function ensureDir(): void {
|
|
87
|
-
try {
|
|
88
|
-
mkdirSync(sessionDir, { recursive: true, mode: 0o700 });
|
|
89
|
-
} catch {
|
|
90
|
-
// non-fatal; clone commands will also create subpaths with mkdir -p
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function cleanupSession(): void {
|
|
95
|
-
if (cleanedUp) return;
|
|
96
|
-
cleanedUp = true;
|
|
97
|
-
safeRmrf(sessionDir);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Belt-and-suspenders: if session_shutdown doesn't fire (some exit paths
|
|
101
|
-
// skip event dispatch), rely on node's process signals. All idempotent.
|
|
102
|
-
process.on("exit", cleanupSession);
|
|
103
|
-
process.on("SIGINT", () => {
|
|
104
|
-
cleanupSession();
|
|
105
|
-
process.exit(130);
|
|
106
|
-
});
|
|
107
|
-
process.on("SIGTERM", () => {
|
|
108
|
-
cleanupSession();
|
|
109
|
-
process.exit(143);
|
|
110
|
-
});
|
|
111
|
-
process.on("uncaughtException", (err) => {
|
|
112
|
-
cleanupSession();
|
|
113
|
-
// Preserve original Node behavior of non-zero exit + stderr trace.
|
|
114
|
-
// eslint-disable-next-line no-console
|
|
115
|
-
console.error(err);
|
|
116
|
-
process.exit(1);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
pi.on("session_start", async (_event, ctx) => {
|
|
120
|
-
ensureDir();
|
|
121
|
-
process.env["ZENDY_SRC_DIR"] = sessionDir;
|
|
122
|
-
const removed = sweepOrphans(BASE_DIR, sessionDir);
|
|
123
|
-
if (ctx.hasUI && removed.length > 0) {
|
|
124
|
-
ctx.ui.notify(
|
|
125
|
-
`[source-cleanup] swept ${removed.length} orphan session dir(s)`,
|
|
126
|
-
"info",
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
pi.on("session_shutdown", async () => {
|
|
132
|
-
cleanupSession();
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
pi.registerCommand("cleanup-src", {
|
|
136
|
-
description:
|
|
137
|
-
"Wipe all Dify source clones (/tmp/dify-*) and orphan zendy session dirs",
|
|
138
|
-
handler: async (_args, ctx) => {
|
|
139
|
-
let entries;
|
|
140
|
-
try {
|
|
141
|
-
entries = readdirSync(BASE_DIR, { withFileTypes: true });
|
|
142
|
-
} catch {
|
|
143
|
-
ctx.ui.notify(`[source-cleanup] cannot read ${BASE_DIR}`, "error");
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
const removed: string[] = [];
|
|
147
|
-
for (const e of entries) {
|
|
148
|
-
if (!e.isDirectory()) continue;
|
|
149
|
-
if (!WIPE_PREFIXES.some((p) => e.name.startsWith(p))) continue;
|
|
150
|
-
const full = join(BASE_DIR, e.name);
|
|
151
|
-
if (full === sessionDir) continue; // never nuke our own live session
|
|
152
|
-
if (safeRmrf(full)) removed.push(full);
|
|
153
|
-
}
|
|
154
|
-
ctx.ui.notify(
|
|
155
|
-
removed.length === 0
|
|
156
|
-
? `[source-cleanup] nothing to remove`
|
|
157
|
-
: `[source-cleanup] removed ${removed.length} dir(s):\n${removed.join("\n")}`,
|
|
158
|
-
"info",
|
|
159
|
-
);
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
}
|
package/extensions/status.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Status slash-command extension.
|
|
3
|
-
*
|
|
4
|
-
* Registers `/status` inside pi. On invocation it shells out to
|
|
5
|
-
* `zendy preflight --json` and renders the result as a single notification.
|
|
6
|
-
*
|
|
7
|
-
* Why subprocess instead of duplicating check logic here? The canonical
|
|
8
|
-
* checks live in `src/preflight.ts` (pi/zcli/github), and the npm-published
|
|
9
|
-
* `zendy` binary is in PATH (pi was launched by it). One source of truth,
|
|
10
|
-
* trivial extension, ~50ms cold start per invocation — fine for an
|
|
11
|
-
* interactive on-demand command.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
15
|
-
import { execFile } from "node:child_process";
|
|
16
|
-
|
|
17
|
-
interface CheckResult {
|
|
18
|
-
name: string;
|
|
19
|
-
label: string;
|
|
20
|
-
level: "fatal" | "core" | "enhanced";
|
|
21
|
-
status: "ok" | "missing" | "auth_error";
|
|
22
|
-
hint: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface PreflightReport {
|
|
26
|
-
results: CheckResult[];
|
|
27
|
-
hasFatal: boolean;
|
|
28
|
-
hasCore: boolean;
|
|
29
|
-
hasEnhanced: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function runZendyPreflight(): Promise<
|
|
33
|
-
{ ok: true; report: PreflightReport } | { ok: false; error: string }
|
|
34
|
-
> {
|
|
35
|
-
return new Promise((resolve) => {
|
|
36
|
-
execFile(
|
|
37
|
-
"zendy",
|
|
38
|
-
["preflight", "--json"],
|
|
39
|
-
{ timeout: 15000, encoding: "utf-8" },
|
|
40
|
-
(err, stdout, stderr) => {
|
|
41
|
-
if (err && (err as NodeJS.ErrnoException).code === "ENOENT") {
|
|
42
|
-
resolve({ ok: false, error: "`zendy` not found in PATH" });
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
if (err) {
|
|
46
|
-
const msg = stderr.trim() || (err as Error).message;
|
|
47
|
-
resolve({ ok: false, error: msg });
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
try {
|
|
51
|
-
const report = JSON.parse(stdout.trim()) as PreflightReport;
|
|
52
|
-
resolve({ ok: true, report });
|
|
53
|
-
} catch {
|
|
54
|
-
resolve({ ok: false, error: `could not parse preflight JSON: ${stdout.slice(0, 200)}` });
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function formatLine(r: CheckResult): string {
|
|
62
|
-
if (r.status === "ok") return ` ✓ ${r.label}`;
|
|
63
|
-
const firstHintLine = r.hint.split("\n")[0] ?? "";
|
|
64
|
-
return ` ✗ ${r.label}${firstHintLine ? ` — ${firstHintLine}` : ""}`;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export default function (pi: ExtensionAPI) {
|
|
68
|
-
pi.registerCommand("status", {
|
|
69
|
-
description: "Show pi / Zendesk / GitHub connection status",
|
|
70
|
-
handler: async (_args, ctx) => {
|
|
71
|
-
const result = await runZendyPreflight();
|
|
72
|
-
if (!result.ok) {
|
|
73
|
-
ctx.ui.notify(`[status] could not run preflight: ${result.error}`, "error");
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
const { report } = result;
|
|
77
|
-
const body = report.results.map(formatLine).join("\n");
|
|
78
|
-
const hasIssue = report.hasFatal || report.hasCore || report.hasEnhanced;
|
|
79
|
-
ctx.ui.notify(`zendy status:\n${body}`, hasIssue ? "error" : "info");
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
|
|
6
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const AGENTS_PATH = join(__dirname, "..", "agents.md");
|
|
8
|
-
|
|
9
|
-
let cachedContext: string | undefined;
|
|
10
|
-
|
|
11
|
-
function loadZendyContext(): string {
|
|
12
|
-
if (cachedContext === undefined) {
|
|
13
|
-
cachedContext = readFileSync(AGENTS_PATH, "utf-8");
|
|
14
|
-
}
|
|
15
|
-
return cachedContext;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default function (pi: ExtensionAPI) {
|
|
19
|
-
pi.on("before_agent_start", async (event) => {
|
|
20
|
-
return {
|
|
21
|
-
systemPrompt: `${event.systemPrompt}\n\n${loadZendyContext()}`,
|
|
22
|
-
};
|
|
23
|
-
});
|
|
24
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: helm-watchdog
|
|
3
|
-
description: "Query Dify Helm chart metadata — values.yaml, container images, validation results, and version info. Use when analyzing Helm-level configuration for a specific Dify Enterprise version."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Dify Helm Watchdog Skill
|
|
7
|
-
|
|
8
|
-
Query the dify-helm-watchdog **HTTP API** to inspect Helm chart data for any cached Dify version.
|
|
9
|
-
|
|
10
|
-
**IMPORTANT: This is a REST API, not a CLI tool. There is no `helm-watchdog` binary. Use `curl` to call the endpoints below.**
|
|
11
|
-
|
|
12
|
-
## Quick Reference — Copy-Paste Commands
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
# Get values.yaml for a version
|
|
16
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0/values"
|
|
17
|
-
|
|
18
|
-
# Get version metadata (chart version → app version mapping)
|
|
19
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0" | jq .
|
|
20
|
-
|
|
21
|
-
# List all container images with their paths and tags
|
|
22
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0/images" | jq '.[] | {path, tag}'
|
|
23
|
-
|
|
24
|
-
# Find a specific component's image (e.g., plugin-connector)
|
|
25
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0/images" | jq '.[] | select(.path | test("plugin-connector"))'
|
|
26
|
-
|
|
27
|
-
# Check image validation status
|
|
28
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0/images?validate=true" | jq '.[] | {path, tag, status}'
|
|
29
|
-
|
|
30
|
-
# Get latest version number
|
|
31
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/latest?versionOnly=true"
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Images API response structure
|
|
35
|
-
|
|
36
|
-
The `/images` endpoint returns a JSON array. Each element has these fields:
|
|
37
|
-
```json
|
|
38
|
-
{
|
|
39
|
-
"path": "langgenius/dify-api", // image repository path
|
|
40
|
-
"tag": "7a1f0e32...", // image tag
|
|
41
|
-
"registry": "docker.io", // registry (may be absent)
|
|
42
|
-
"valuesPath": "api.image" // location in values.yaml
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Key: the field is `.path`, not `.name` or `.repository`.
|
|
47
|
-
|
|
48
|
-
## When to Use
|
|
49
|
-
|
|
50
|
-
- Looking up `values.yaml` for a specific Dify chart version
|
|
51
|
-
- Checking what container images a chart version uses
|
|
52
|
-
- Finding the latest chart version
|
|
53
|
-
- Validating chart image availability
|
|
54
|
-
- Answering customer questions about Helm configuration, default values, or image tags
|
|
55
|
-
|
|
56
|
-
## When NOT to Use
|
|
57
|
-
|
|
58
|
-
- Modifying chart values or deploying — this is read-only
|
|
59
|
-
- Anything outside the Helm chart layer (application code, runtime behavior)
|
|
60
|
-
|
|
61
|
-
## Base URL
|
|
62
|
-
|
|
63
|
-
```
|
|
64
|
-
https://dify-helm-watchdog.vercel.app/api/v1
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## API Endpoints
|
|
68
|
-
|
|
69
|
-
### List cached versions
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions" | jq .
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Get latest version
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/latest"
|
|
79
|
-
# Plain text version number only:
|
|
80
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/latest?versionOnly=true"
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Get version metadata
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0" | jq .
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
Returns chart version, app version, creation date, and asset URLs.
|
|
90
|
-
|
|
91
|
-
### Get values.yaml
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0/values"
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Returns the full `values.yaml` for the requested chart version. This is the most commonly used endpoint — use it to check default configuration, environment variables, image tags, and feature flags.
|
|
98
|
-
|
|
99
|
-
### Get container images
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
# JSON output
|
|
103
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0/images" | jq .
|
|
104
|
-
# With validation status
|
|
105
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0/images?validate=true" | jq .
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
Lists all container image references from the chart's values. Useful for answering questions about image tags (`latest` vs pinned), base images, and vulnerability scoping.
|
|
109
|
-
|
|
110
|
-
### Get validation results
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
# All validations
|
|
114
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0/validation" | jq .
|
|
115
|
-
# Only missing images
|
|
116
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/versions/3.8.0/validation?status=MISSING" | jq .
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### Inspect cache metadata
|
|
120
|
-
|
|
121
|
-
```bash
|
|
122
|
-
curl -s "https://dify-helm-watchdog.vercel.app/api/v1/cache" | jq .
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
## Practical Guidance
|
|
126
|
-
|
|
127
|
-
1. **Start with version metadata** to confirm the chart version exists and get the app version mapping (e.g., chart 3.8.0 → app 1.12.0).
|
|
128
|
-
2. **Use values.yaml** to answer configuration questions — most customer inquiries about Helm settings can be resolved here.
|
|
129
|
-
3. **Use images** endpoint when the question is about container images, tags, or vulnerability scope.
|
|
130
|
-
4. When a customer reports an issue on a specific version, always pull the values.yaml for **that exact version** — defaults change between releases.
|
|
131
|
-
5. Output is JSON unless otherwise noted (values endpoint returns raw YAML).
|
|
132
|
-
|
|
133
|
-
## Version Mapping
|
|
134
|
-
|
|
135
|
-
Chart versions map to Dify app versions. Common mappings:
|
|
136
|
-
- Chart 3.8.0 → App 1.12.0
|
|
137
|
-
- Chart 3.7.5 → App 1.11.4
|
|
138
|
-
|
|
139
|
-
Use the version metadata endpoint to confirm the mapping for any version.
|
|
140
|
-
|
|
141
|
-
## Notes for the Agent
|
|
142
|
-
|
|
143
|
-
- All endpoints are public and read-only, no authentication needed for GET requests.
|
|
144
|
-
- Use `curl -s` and pipe to `jq` for readable output.
|
|
145
|
-
- The values.yaml can be large — if you only need a specific section, pipe through `grep` or use `yq` if available.
|
|
146
|
-
- When comparing versions, pull values for both and diff them.
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: source-check
|
|
3
|
-
description: "Clone and analyze Dify source code to investigate customer issues. Knows the repo map: enterprise backend/frontend, open-source core, plugin daemon, sandbox. Human-triggered only."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Dify Source Analysis Skill
|
|
7
|
-
|
|
8
|
-
Clone the correct Dify repository and analyze source code to investigate customer issues.
|
|
9
|
-
|
|
10
|
-
## When to Use
|
|
11
|
-
|
|
12
|
-
- The user explicitly asks to look at the source code
|
|
13
|
-
- A question cannot be answered from Helm chart values alone
|
|
14
|
-
|
|
15
|
-
## When NOT to Use
|
|
16
|
-
|
|
17
|
-
- Do NOT proactively decide to clone source code — wait for the user to ask
|
|
18
|
-
- Do NOT use for questions answerable from values.yaml or documentation
|
|
19
|
-
|
|
20
|
-
## Repository Map
|
|
21
|
-
|
|
22
|
-
**First, determine which repo to clone based on the problem area:**
|
|
23
|
-
|
|
24
|
-
**Clone destination:** always clone under `"$ZENDY_SRC_DIR"` (set by the `source-cleanup`
|
|
25
|
-
extension at session start). The extension will wipe the whole directory when the
|
|
26
|
-
session ends, so anything inside is guaranteed to be cleaned up — even if you forget.
|
|
27
|
-
If for some reason `$ZENDY_SRC_DIR` is not set, fall back to `/tmp` but tell the user.
|
|
28
|
-
|
|
29
|
-
| Problem area | Repo | Access | Language | Clone command |
|
|
30
|
-
|---|---|---|---|---|
|
|
31
|
-
| SSO, token, session, SCIM, license, audit, branding, MFA, password policy | `langgenius/dify-enterprise` | private | Go | `git clone --depth 1 --branch <tag> git@github.com:langgenius/dify-enterprise.git "$ZENDY_SRC_DIR/dify-enterprise-<tag>"` |
|
|
32
|
-
| Enterprise Dashboard UI, admin console frontend | `langgenius/dify-enterprise-frontend` | private | TypeScript | `git clone --depth 1 --branch <tag> git@github.com:langgenius/dify-enterprise-frontend.git "$ZENDY_SRC_DIR/dify-enterprise-frontend-<tag>"` |
|
|
33
|
-
| API, workflow, knowledge base, model provider, RAG, chat | `langgenius/dify` | public | Python | `git clone --depth 1 --branch <tag> git@github.com:langgenius/dify.git "$ZENDY_SRC_DIR/dify-<tag>"` |
|
|
34
|
-
| Plugin runtime, plugin execution | `langgenius/dify-plugin-daemon` | public | Go/Python | `git clone --depth 1 --branch <tag> git@github.com:langgenius/dify-plugin-daemon.git "$ZENDY_SRC_DIR/dify-plugin-daemon-<tag>"` |
|
|
35
|
-
| Code sandbox execution | `langgenius/dify-sandbox` | public | Go | `git clone --depth 1 --branch <tag> git@github.com:langgenius/dify-sandbox.git "$ZENDY_SRC_DIR/dify-sandbox-<tag>"` |
|
|
36
|
-
|
|
37
|
-
Enterprise repos also contain these components (all in dify-enterprise):
|
|
38
|
-
- **gateway** — enterprise API gateway (`cmd/gateway/`, `pkg/gateway/`)
|
|
39
|
-
- **plugin-connector** — plugin pod orchestration on K8s (`cmd/plugin-connector/`, `pkg/connector/`)
|
|
40
|
-
- **plugin-manager** — enterprise plugin management (`cmd/plugin-manager/`, `pkg/plugin-manager/`)
|
|
41
|
-
- **plugin-crd** — K8s CRD controller for plugins (`cmd/plugin-crd/`, `pkg/plugincrd/`)
|
|
42
|
-
- **audit** — audit logging (`cmd/audit/`, `pkg/audit/`)
|
|
43
|
-
|
|
44
|
-
## Version Mapping
|
|
45
|
-
|
|
46
|
-
Customer's Dify version → correct git tag:
|
|
47
|
-
|
|
48
|
-
1. Get chart version from Zendesk ticket fields (e.g., `3.8.0`)
|
|
49
|
-
2. Use helm-watchdog to get the image tags from values.yaml:
|
|
50
|
-
- `enterprise.image.tag` → tag for `dify-enterprise` and `dify-enterprise-frontend` (e.g., `0.15.0`)
|
|
51
|
-
- `api.image.tag` → tag for `dify` (usually a commit hash, e.g., `7a1f0e32...`)
|
|
52
|
-
- `pluginDaemon.image.tag` → tag for `dify-plugin-daemon`
|
|
53
|
-
- `sandbox.image.tag` → tag for `dify-sandbox`
|
|
54
|
-
|
|
55
|
-
## dify-enterprise Directory Structure (Go)
|
|
56
|
-
|
|
57
|
-
```
|
|
58
|
-
cmd/ # Entry points (one per component)
|
|
59
|
-
├── enterprise/ # Main enterprise backend
|
|
60
|
-
├── gateway/ # API gateway
|
|
61
|
-
├── audit/ # Audit service
|
|
62
|
-
├── plugin-connector/ # Plugin K8s orchestrator
|
|
63
|
-
├── plugin-manager/ # Plugin manager
|
|
64
|
-
├── plugin-crd/ # K8s CRD controller
|
|
65
|
-
└── plugin-shader/ # Plugin image builder
|
|
66
|
-
|
|
67
|
-
pkg/
|
|
68
|
-
├── enterprise/
|
|
69
|
-
│ └── service/ # Core business logic
|
|
70
|
-
│ ├── console-sso.go # Console SSO login (SAML/OIDC/OAuth2)
|
|
71
|
-
│ ├── web-sso.go # WebApp SSO login
|
|
72
|
-
│ ├── dashboard-sso.go # Dashboard SSO
|
|
73
|
-
│ ├── cookie.go # Cookie/session management
|
|
74
|
-
│ ├── ssoconfig.go # SSO configuration
|
|
75
|
-
│ ├── member.go # User/member management
|
|
76
|
-
│ ├── license.go # License validation
|
|
77
|
-
│ ├── mfa.go # Multi-factor auth
|
|
78
|
-
│ ├── password-policy.go # Password policy
|
|
79
|
-
│ ├── scim.go # SCIM provisioning
|
|
80
|
-
│ ├── scim-users.go # SCIM user sync
|
|
81
|
-
│ ├── scim-groups.go # SCIM group sync
|
|
82
|
-
│ ├── branding.go # Custom branding
|
|
83
|
-
│ ├── workspace.go # Workspace management
|
|
84
|
-
│ ├── admin-*.go # Admin operations
|
|
85
|
-
│ └── webapp.go # WebApp config
|
|
86
|
-
├── sysconf/
|
|
87
|
-
│ ├── keys.go # Configuration key definitions
|
|
88
|
-
│ └── values.go # Default values
|
|
89
|
-
├── auth/ # Authentication
|
|
90
|
-
├── connector/ # Plugin connector logic
|
|
91
|
-
├── gateway/ # Gateway logic
|
|
92
|
-
├── plugin/ # Plugin management
|
|
93
|
-
├── plugin-manager/ # Plugin manager logic
|
|
94
|
-
├── plugincrd/ # K8s CRD logic
|
|
95
|
-
├── audit/ # Audit logic
|
|
96
|
-
├── kube/ # Kubernetes utilities
|
|
97
|
-
└── data/ # Data layer
|
|
98
|
-
|
|
99
|
-
ts/ # TypeScript code
|
|
100
|
-
├── connector/ # Plugin connector frontend
|
|
101
|
-
├── enterprise_client/ # Enterprise API client
|
|
102
|
-
└── dify/ # Dify integrations
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## dify (open-source) Directory Structure (Python)
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
api/ # Backend API (Flask)
|
|
109
|
-
├── controllers/ # HTTP handlers
|
|
110
|
-
├── core/
|
|
111
|
-
│ ├── workflow/ # Workflow engine
|
|
112
|
-
│ ├── rag/ # RAG pipeline
|
|
113
|
-
│ ├── model_runtime/ # Model provider integrations
|
|
114
|
-
│ ├── app/ # App orchestration
|
|
115
|
-
│ └── tools/ # Built-in tools
|
|
116
|
-
├── services/ # Business logic
|
|
117
|
-
├── models/ # Database models
|
|
118
|
-
└── configs/ # Configuration
|
|
119
|
-
|
|
120
|
-
web/ # Frontend (Next.js / TypeScript)
|
|
121
|
-
├── app/ # Pages
|
|
122
|
-
├── components/ # UI components
|
|
123
|
-
└── service/ # API client
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## Analysis Approach
|
|
127
|
-
|
|
128
|
-
1. **grep first** — find relevant files by keyword (feature name, config key, error message)
|
|
129
|
-
2. **Read identified files** — understand the logic
|
|
130
|
-
3. **Trace the flow** — API endpoint → handler → service → data layer
|
|
131
|
-
4. **Compare** with the customer's reported behavior
|
|
132
|
-
5. **Conclude** — bug, misconfiguration, or expected behavior
|
|
133
|
-
|
|
134
|
-
## Rules
|
|
135
|
-
|
|
136
|
-
- Always shallow clone (`--depth 1`) for speed
|
|
137
|
-
- State confidence level: "confirmed from code" vs "inferred from structure"
|
|
138
|
-
- Read-only — never modify source code
|
|
139
|
-
- Clone into `"$ZENDY_SRC_DIR"`. The `source-cleanup` extension wipes this directory
|
|
140
|
-
on session shutdown, so manual `rm -rf` after analysis is no longer required.
|
|
141
|
-
If the user asks for immediate cleanup mid-session, use the `/cleanup-src` slash
|
|
142
|
-
command (wipes `/tmp/dify-*` and orphan session dirs).
|
|
143
|
-
- If clone fails (permission denied), tell the user to configure SSH keys
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: zendesk-cli
|
|
3
|
-
description: "Zendesk ticket lookup via the zcli CLI. Provides ticket metadata, comment threads, and search — all as JSON."
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# zendesk-cli
|
|
7
|
-
|
|
8
|
-
`zcli` is a Zendesk CLI that outputs JSON. Use it to fetch tickets, comments, and search results.
|
|
9
|
-
|
|
10
|
-
## Quick start
|
|
11
|
-
|
|
12
|
-
Discover all commands and options:
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
zcli --help
|
|
16
|
-
zcli <command> --help
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Install (if missing)
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
npm install -g @tplog/zendesk-cli
|
|
23
|
-
zcli configure
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Key behaviors the agent must know
|
|
27
|
-
|
|
28
|
-
- **`zcli <email>` is assignee lookup, not requester.** This is the most common mistake.
|
|
29
|
-
- **`zcli follower <email>`** is a separate command — don't try to filter assignee results manually.
|
|
30
|
-
- **Output is already JSON.** No `--json` flag needed. Summarize directly from stdout.
|
|
31
|
-
- **When summarizing a ticket, always parallel-call both:**
|
|
32
|
-
```bash
|
|
33
|
-
zcli <id> # ticket metadata
|
|
34
|
-
zcli comments <id> # comment thread
|
|
35
|
-
```
|
|
36
|
-
Ticket metadata alone is not enough for a complete summary.
|
|
37
|
-
- **Errors are also JSON on stdout** with non-zero exit code. Check stdout, not just stderr.
|