@zibby/skills 0.1.95 → 0.2.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.
Files changed (78) hide show
  1. package/README.md +1 -1
  2. package/dist/artifact.d.ts +1 -115
  3. package/dist/browser.d.ts +10 -19
  4. package/dist/chartRender.d.ts +46 -57
  5. package/dist/chartRender.js +1 -1
  6. package/dist/chat-memory.d.ts +26 -330
  7. package/dist/chat-notify.d.ts +30 -409
  8. package/dist/chat-notify.js +3 -3
  9. package/dist/chatProgress.d.ts +28 -47
  10. package/dist/code-scan.d.ts +52 -58
  11. package/dist/codeStats.d.ts +36 -136
  12. package/dist/codeStats.js +1 -1
  13. package/dist/codebaseMemory.d.ts +52 -32
  14. package/dist/codebaseMemory.js +2 -2
  15. package/dist/core-tools.d.ts +10 -131
  16. package/dist/datasetStore.d.ts +52 -179
  17. package/dist/datasetStore.js +12 -3
  18. package/dist/discord.d.ts +32 -68
  19. package/dist/figma.d.ts +5 -408
  20. package/dist/function-skill.d.ts +23 -135
  21. package/dist/function-skill.js +1 -1
  22. package/dist/gbrain.d.ts +46 -114
  23. package/dist/git-write.d.ts +45 -137
  24. package/dist/git-write.js +6 -6
  25. package/dist/git.d.ts +2 -73
  26. package/dist/github.d.ts +2 -1202
  27. package/dist/gitlab.d.ts +55 -1059
  28. package/dist/gitlab.js +2 -2
  29. package/dist/googleDocs.d.ts +39 -175
  30. package/dist/hubspot.d.ts +1 -381
  31. package/dist/index.d.ts +19 -12
  32. package/dist/index.js +157 -148
  33. package/dist/integrations.d.ts +2 -2
  34. package/dist/jira.d.ts +2 -532
  35. package/dist/jira.js +4 -4
  36. package/dist/kvMemory.d.ts +47 -78
  37. package/dist/lark.d.ts +2 -161
  38. package/dist/lark.js +1 -1
  39. package/dist/larkDocs.d.ts +35 -236
  40. package/dist/linear.d.ts +36 -343
  41. package/dist/linkedin.d.ts +10 -120
  42. package/dist/llm-billing.d.ts +92 -180
  43. package/dist/llm-billing.js +1 -1
  44. package/dist/memory.d.ts +11 -137
  45. package/dist/notion.d.ts +28 -276
  46. package/dist/notion.js +4 -4
  47. package/dist/opendesign.d.ts +24 -202
  48. package/dist/opendesign.js +2 -2
  49. package/dist/package.json +3 -2
  50. package/dist/plane.d.ts +40 -24
  51. package/dist/report.d.ts +153 -110
  52. package/dist/review-dedup.d.ts +8 -8
  53. package/dist/review.d.ts +12 -2
  54. package/dist/reviewMemoryIo.d.ts +37 -3
  55. package/dist/reviewRecord.d.ts +41 -47
  56. package/dist/sentry.d.ts +25 -22
  57. package/dist/skill-installer.d.ts +11 -86
  58. package/dist/slack.d.ts +1 -284
  59. package/dist/socialCard.d.ts +35 -89
  60. package/dist/test-runner.d.ts +1 -220
  61. package/dist/trackers/github-adapter.d.ts +39 -94
  62. package/dist/trackers/index.d.ts +25 -18
  63. package/dist/trackers/jira-adapter.d.ts +20 -88
  64. package/dist/trackers/linear-adapter.d.ts +24 -87
  65. package/dist/trackers/plane-adapter.d.ts +29 -85
  66. package/dist/trackers/plane-adapter.js +1 -1
  67. package/dist/trackers/types.d.ts +1 -186
  68. package/dist/triggerAgent.d.ts +26 -42
  69. package/dist/triggerAgent.js +1 -1
  70. package/dist/workflow-builder.d.ts +11 -245
  71. package/docs/cli-reference.md +33 -0
  72. package/docs/concepts/designing-agents.md +201 -0
  73. package/docs/self-host/backup-restore.md +52 -0
  74. package/docs/self-host/index.md +75 -0
  75. package/docs/self-host/storage.md +50 -0
  76. package/docs/self-host/troubleshooting.md +48 -0
  77. package/docs/self-host/upgrade.md +81 -0
  78. package/package.json +3 -2
@@ -1,89 +1,26 @@
1
- export namespace linearAdapter {
2
- export let id: string;
3
- export { toStateCategory };
4
- export { toNeutral };
5
- /**
6
- * listCandidates — poll issues filtered by team/state/label/assignee/cursor.
7
- * Linear ignores free-text `query`; pass structured filters via opts/ctx.
8
- * @param {import('./types.js').ListCandidatesOptions & {ctx?: object}} [opts]
9
- * @returns {Promise<import('./types.js').NeutralTicket[]>}
10
- */
11
- export function listCandidates(opts?: import("./types.js").ListCandidatesOptions & {
12
- ctx?: object;
13
- }): Promise<import("./types.js").NeutralTicket[]>;
14
- /** getTicket — one issue by identifier (ENG-123) or uuid. */
15
- export function getTicket(key: any): Promise<{
16
- id: string;
17
- key: any;
18
- title: any;
19
- body: any;
20
- state: any;
21
- stateCategory: "unknown" | "todo" | "in_progress" | "done" | "blocked";
22
- assignee: any;
23
- url: any;
24
- _raw: any;
25
- }>;
26
- /** getComments — newest first. */
27
- export function getComments(key: any): Promise<any>;
28
- /** addComment — markdown body. */
29
- export function addComment(key: any, body: any): Promise<{
30
- ok: boolean;
31
- id: any;
32
- }>;
33
- /**
34
- * transition — set the issue's workflow state by target NAME. The skill
35
- * resolves the name to the team's matching state id (exact → type-alias →
36
- * fuzzy). No transition object in Linear.
37
- */
38
- export function transition(key: any, targetStateName: any): Promise<{
39
- ok: boolean;
40
- error: any;
41
- _raw: any;
42
- stateAfter?: undefined;
43
- stateCategoryAfter?: undefined;
44
- } | {
45
- ok: boolean;
46
- stateAfter: any;
47
- stateCategoryAfter: "unknown" | "todo" | "in_progress" | "done" | "blocked";
48
- _raw: any;
49
- error?: undefined;
50
- }>;
51
- /**
52
- * linkPullRequest — native Linear attachment; fall back to a comment.
53
- */
54
- export function linkPullRequest(key: any, prUrl: any, title: any): Promise<{
55
- ok: boolean;
56
- via: string;
57
- error?: undefined;
58
- } | {
59
- ok: boolean;
60
- via: string;
61
- error: string;
62
- }>;
63
- }
64
- export default linearAdapter;
65
- /**
66
- * Map a Linear state into the neutral 5-bucket category.
67
- * @param {{name?: string, type?: string}} [state]
68
- * @returns {'todo'|'in_progress'|'done'|'blocked'|'unknown'}
69
- */
70
- declare function toStateCategory(state?: {
71
- name?: string;
72
- type?: string;
73
- }): "todo" | "in_progress" | "done" | "blocked" | "unknown";
74
1
  /**
75
- * Build a NeutralTicket from the linear.js tool projection. The list and get
76
- * tools both expose `state` (name) + `stateType` (the WorkflowState type); we
77
- * bucket off the type, keep the raw name as `state`.
2
+ * Linear tracker adapter projects Linear onto the neutral TrackerAdapter
3
+ * contract.
4
+ * ============================================================================
5
+ *
6
+ * Thin wrapper over linear.js. The skill already exposes everything we need as
7
+ * tools (list_issues / get_issue / get_comments / add_comment / update_state /
8
+ * link_attachment) and does the fuzzy state resolution internally, so the
9
+ * adapter is almost entirely the toNeutral mapping + plumbing.
10
+ *
11
+ * State mapping: Linear workflow states carry a `type` ∈
12
+ * triage | backlog | unstarted | started | completed | canceled
13
+ * which maps onto the neutral buckets. Linear has no native "blocked" type, so
14
+ * 'blocked' is only ever derived from a state NAME match (best-effort).
15
+ *
16
+ * transition == update_state: Linear has no transition object; you set
17
+ * issue.stateId to any state in the same team. The skill resolves a target
18
+ * NAME → the team's matching state id (exact → type-alias → fuzzy).
19
+ *
20
+ * linkPullRequest == link_attachment: Linear has native attachments, the
21
+ * first-class way to hang a PR on an issue. Fall back to a comment if it fails.
22
+ *
23
+ * Auth/config is inherited from linear.js (LINEAR_API_KEY / LINEAR_OAUTH_TOKEN).
78
24
  */
79
- declare function toNeutral(issue: any): {
80
- id: string;
81
- key: any;
82
- title: any;
83
- body: any;
84
- state: any;
85
- stateCategory: "unknown" | "todo" | "in_progress" | "done" | "blocked";
86
- assignee: any;
87
- url: any;
88
- _raw: any;
89
- };
25
+ export declare const linearAdapter: any;
26
+ export default linearAdapter;
@@ -1,3 +1,29 @@
1
+ /**
2
+ * Plane tracker adapter — projects Plane onto the neutral TrackerAdapter
3
+ * contract. Promoted from strategy/plane-app-draft/plane-adapter.draft.js.
4
+ * ============================================================================
5
+ *
6
+ * Mirrors the proven shape of linear.js: ONE auth chokepoint (planeFetch, with
7
+ * X-API-Key), the 6 neutral methods, and a NeutralTicket with `state` (raw
8
+ * name), `stateCategory` (normalized bucket) and `_raw`.
9
+ *
10
+ * Plane specifics that drove the design (verified — see RESEARCH.md):
11
+ * - Auth: personal access token in header `X-API-Key: <token>`. Self-hosted ⇒
12
+ * base URL is the TENANT's host (https://<host>/api/v1), NOT api.plane.so.
13
+ * Both come from env (same posture as linear.js).
14
+ * - Scoping: every issue is workspace_slug → project_id → id. No global list,
15
+ * so the adapter is bound to a (workspace, project) via env or per-call ctx.
16
+ * - States carry a `group` ∈ {backlog, unstarted, started, completed,
17
+ * cancelled} — the normalization key. NO transition object: you PATCH the
18
+ * work-item `state` to a target state uuid (like Linear, unlike Jira).
19
+ * - List endpoints are cursor-paginated:
20
+ * { results, next_cursor, prev_cursor, count, total_results, ... }
21
+ * per_page default & max 100; cursor format "value:offset:is_prev".
22
+ * - Comments are HTML (comment_html), NOT markdown. We wrap plaintext.
23
+ *
24
+ * HONEST TODOs (inline) are Plane-version-specific details not fully confirmable
25
+ * from the public docs without a live instance — kept from the research draft.
26
+ */
1
27
  /**
2
28
  * Low-level Plane REST helper — the SINGLE auth chokepoint (cf. linearFetch).
3
29
  * Keep token + base-url resolution here; never re-implement at call sites.
@@ -8,94 +34,12 @@
8
34
  * @param {{method?:string, body?:any, query?:object, headers?:object}} [opts]
9
35
  * @returns {Promise<any>} parsed JSON (or {} for empty body)
10
36
  */
11
- export function planeFetch(path: string, opts?: {
12
- method?: string;
13
- body?: any;
14
- query?: object;
15
- headers?: object;
16
- }): Promise<any>;
37
+ export declare function planeFetch(path: any, opts?: any): Promise<any>;
17
38
  /**
18
39
  * Normalize a Plane state into the neutral 5-bucket category.
19
40
  * @param {{name?:string, group?:string}} [state]
20
41
  * @returns {'todo'|'in_progress'|'done'|'blocked'|'unknown'}
21
42
  */
22
- export function toStateCategory(state?: {
23
- name?: string;
24
- group?: string;
25
- }): "todo" | "in_progress" | "done" | "blocked" | "unknown";
26
- export namespace planeAdapter {
27
- export let id: string;
28
- export let envKeys: string[];
29
- export { planeFetch };
30
- export { toStateCategory };
31
- /**
32
- * listCandidates — poll work items for a (workspace, project).
33
- * @param {import('./types.js').ListCandidatesOptions & {ctx?: object}} [opts]
34
- * @returns {Promise<import('./types.js').NeutralTicket[]>}
35
- */
36
- export function listCandidates(opts?: import("./types.js").ListCandidatesOptions & {
37
- ctx?: object;
38
- }): Promise<import("./types.js").NeutralTicket[]>;
39
- /**
40
- * getTicket — one work item by uuid (Plane addresses work items by uuid, NOT
41
- * by the PROJ-42 human key).
42
- * TODO: if `key` looks like "PROJ-42", resolve sequence_id → uuid via a
43
- * filtered list call. For now assume a uuid.
44
- */
45
- export function getTicket(key: any, ctx?: {}): Promise<{
46
- id: any;
47
- key: any;
48
- title: any;
49
- body: any;
50
- state: any;
51
- stateCategory: "unknown" | "todo" | "in_progress" | "done" | "blocked";
52
- assignee: string;
53
- url: string;
54
- _raw: any;
55
- }>;
56
- /** getComments — newest first. */
57
- export function getComments(key: any, ctx?: {}): Promise<any>;
58
- /**
59
- * addComment — Plane comments are HTML, not markdown. We wrap plaintext in a
60
- * <p> so a markdown-y body at least renders as text.
61
- * TODO: confirm the API accepts comment_html on POST (vs comment_stripped),
62
- * and whether it sanitizes/strips.
63
- */
64
- export function addComment(key: any, body: any, ctx?: {}): Promise<{
65
- ok: boolean;
66
- id: any;
67
- _raw: any;
68
- }>;
69
- /**
70
- * transition — Plane has NO transition object (like Linear). Resolve the
71
- * target state NAME (or a neutral category word) to the project's matching
72
- * state uuid, then PATCH work-item { state: <uuid> }.
73
- */
74
- export function transition(key: any, targetStateName: any, ctx?: {}): Promise<{
75
- ok: boolean;
76
- error: string;
77
- availableStates: any;
78
- stateAfter?: undefined;
79
- stateCategoryAfter?: undefined;
80
- _raw?: undefined;
81
- } | {
82
- ok: boolean;
83
- stateAfter: any;
84
- stateCategoryAfter: "unknown" | "todo" | "in_progress" | "done" | "blocked";
85
- _raw: any;
86
- error?: undefined;
87
- availableStates?: undefined;
88
- }>;
89
- /**
90
- * linkPullRequest — Plane has no first-class "attachment URL on issue" like
91
- * Linear's attachmentCreate. The portable path is a comment with the link.
92
- * (Plane does have a GitHub *integration* for repo-level linking, but that's
93
- * an installed integration, not a per-issue API write.)
94
- * TODO: if a target Plane exposes a link/attachment endpoint, prefer it.
95
- */
96
- export function linkPullRequest(key: any, prUrl: any, title: any, ctx?: {}): Promise<{
97
- ok: boolean;
98
- via: string;
99
- }>;
100
- }
43
+ export declare function toStateCategory(state: any): any;
44
+ export declare const planeAdapter: any;
101
45
  export default planeAdapter;
@@ -1 +1 @@
1
- var f=(process.env.PLANE_API_URL||"https://api.plane.so/api/v1").replace(/\/+$/,""),A=process.env.PLANE_WORKSPACE_SLUG||"",w=process.env.PLANE_PROJECT_ID||"";function k(){let e=process.env.PLANE_API_KEY||process.env.PLANE_OAUTH_TOKEN;if(!e)throw new Error("Plane is not connected: set PLANE_API_KEY (personal access token).");return e}function p(e={}){let t=e.workspaceSlug||A,o=e.projectId||w;if(!t||!o)throw new Error("Plane scope missing: provide workspaceSlug + projectId (env PLANE_WORKSPACE_SLUG / PLANE_PROJECT_ID or per-call ctx).");return{workspaceSlug:t,projectId:o}}async function d(e,t={}){let o=`${f}${e}`;if(t.query&&Object.keys(t.query).length){let a=new URLSearchParams;for(let[c,i]of Object.entries(t.query))i!=null&&i!==""&&a.set(c,String(i));let n=a.toString();n&&(o+=(o.includes("?")?"&":"?")+n)}let r=await fetch(o,{method:t.method||"GET",headers:{"X-API-Key":k(),Accept:"application/json",...t.body?{"Content-Type":"application/json"}:{},...t.headers},body:t.body?JSON.stringify(t.body):void 0});if(!r.ok){let a=await r.text().catch(()=>"");throw new Error(`Plane API ${r.status}: ${a.slice(0,300)}`)}let s=await r.text().catch(()=>"");if(!s||!s.trim())return{};try{return JSON.parse(s)}catch{return{raw:s}}}var P={backlog:"todo",unstarted:"todo",started:"in_progress",completed:"done",cancelled:"done"},S=/\b(blocked|on[\s-]?hold|waiting|stuck)\b/i;function u(e){return e?e.name&&S.test(e.name)?"blocked":P[e.group]||"unknown":"unknown"}var m=new Map,I=300*1e3;async function g(e){let{workspaceSlug:t,projectId:o}=p(e),r=m.get(o);if(r&&Date.now()-r.fetchedAt<I)return r.states;let s=await d(`/workspaces/${encodeURIComponent(t)}/projects/${encodeURIComponent(o)}/states/`,{query:{per_page:100}}),a=(s.results||s||[]).map(n=>({id:n.id,name:n.name,group:n.group,color:n.color}));return m.set(o,{fetchedAt:Date.now(),states:a}),a}function l(e){return String(e||"").toLowerCase().replace(/\s+/g,"").replace(/[()\-_::"'`]/g,"")}function C(e,t){let o=l(t);if(!o)return null;let r=e.find(a=>l(a.name)===o);if(r)return r;let s={todo:["todo","backlog","open","unstarted"],inprogress:["inprogress","started","doing","wip"],done:["done","completed","closed","resolved","cancelled","canceled"],blocked:["blocked","onhold","waiting"]};for(let[,a]of Object.entries(s)){if(!a.some(i=>l(i)===o))continue;let n=o==="done"?"completed":o==="inprogress"?"started":"unstarted",c=e.find(i=>i.group===n);if(c)return c}return null}async function _(e,t){let r=(await g(t).catch(()=>[])).find(i=>i.id===e.state)||null,{workspaceSlug:s,projectId:a}=p(t),n=t.projectIdentifier&&e.sequence_id!=null?`${t.projectIdentifier}-${e.sequence_id}`:e.sequence_id!=null?String(e.sequence_id):e.id,c=e.assignees||[];return{id:e.id,key:n,title:e.name||"",body:e.description_html||e.description_stripped||e.description||"",state:r?r.name:null,stateCategory:u(r),assignee:c.length?String(c[0]):null,url:t.baseWebUrl?`${t.baseWebUrl}/${s}/projects/${a}/issues/${e.id}`:null,_raw:e}}var E={id:"plane",envKeys:["PLANE_API_KEY","PLANE_OAUTH_TOKEN","PLANE_API_URL","PLANE_WORKSPACE_SLUG","PLANE_PROJECT_ID"],planeFetch:d,toStateCategory:u,async listCandidates(e={}){let t=e.ctx||{},{workspaceSlug:o,projectId:r}=p(t),s={per_page:Math.min(Number(e.limit)||50,100),cursor:e.cursor};e.state&&(s.state=e.state),e.updatedAfter&&(s.updated_at__gte=e.updatedAfter);let n=(await d(`/workspaces/${encodeURIComponent(o)}/projects/${encodeURIComponent(r)}/work-items/`,{query:s})).results||[];return e.updatedAfter&&(n=n.filter(c=>String(c.updated_at)>String(e.updatedAfter))),Promise.all(n.map(c=>_(c,t)))},async getTicket(e,t={}){let{workspaceSlug:o,projectId:r}=p(t),s=await d(`/workspaces/${encodeURIComponent(o)}/projects/${encodeURIComponent(r)}/work-items/${encodeURIComponent(e)}/`);return!s||!s.id?null:_(s,t)},async getComments(e,t={}){let{workspaceSlug:o,projectId:r}=p(t);return((await d(`/workspaces/${encodeURIComponent(o)}/projects/${encodeURIComponent(r)}/work-items/${encodeURIComponent(e)}/comments/`,{query:{per_page:100}})).results||[]).map(n=>({id:n.id,author:n.actor||n.actor_detail?.display_name||"Unknown",body:n.comment_html||n.comment_stripped||"",createdAt:n.created_at||null,updatedAt:n.updated_at||null,_raw:n})).sort((n,c)=>String(c.createdAt).localeCompare(String(n.createdAt)))},async addComment(e,t,o={}){let{workspaceSlug:r,projectId:s}=p(o),n=/<[a-z][\s\S]*>/i.test(String(t||""))?String(t):`<p>${String(t||"")}</p>`,c=await d(`/workspaces/${encodeURIComponent(r)}/projects/${encodeURIComponent(s)}/work-items/${encodeURIComponent(e)}/comments/`,{method:"POST",body:{comment_html:n}});return{ok:!!c.id,id:c.id||null,_raw:c}},async transition(e,t,o={}){let{workspaceSlug:r,projectId:s}=p(o),a=await g(o),n=C(a,t);if(!n)return{ok:!1,error:`No Plane state matches "${t}" in this project`,availableStates:a.map(i=>({id:i.id,name:i.name,group:i.group}))};let c=await d(`/workspaces/${encodeURIComponent(r)}/projects/${encodeURIComponent(s)}/work-items/${encodeURIComponent(e)}/`,{method:"PATCH",body:{state:n.id}});return{ok:!!c.id,stateAfter:n.name,stateCategoryAfter:u(n),_raw:c}},async linkPullRequest(e,t,o,r={}){let s=o?`${o}: `:"Linked PR: ";return{ok:!!(await this.addComment(e,`<p>${s}<a href="${t}">${t}</a></p>`,r)).ok,via:"comment"}}},h=E;export{h as default,E as planeAdapter,d as planeFetch,u as toStateCategory};
1
+ var f=(process.env.PLANE_API_URL||"https://api.plane.so/api/v1").replace(/\/+$/,""),A=process.env.PLANE_WORKSPACE_SLUG||"",w=process.env.PLANE_PROJECT_ID||"";function y(){let e=process.env.PLANE_API_KEY||process.env.PLANE_OAUTH_TOKEN;if(!e)throw new Error("Plane is not connected: set PLANE_API_KEY (personal access token).");return e}function p(e={}){let t=e.workspaceSlug||A,o=e.projectId||w;if(!t||!o)throw new Error("Plane scope missing: provide workspaceSlug + projectId (env PLANE_WORKSPACE_SLUG / PLANE_PROJECT_ID or per-call ctx).");return{workspaceSlug:t,projectId:o}}async function d(e,t={}){let o=`${f}${e}`;if(t.query&&Object.keys(t.query).length){let a=new URLSearchParams;for(let[c,i]of Object.entries(t.query))i!=null&&i!==""&&a.set(c,String(i));let n=a.toString();n&&(o+=(o.includes("?")?"&":"?")+n)}let r=await fetch(o,{method:t.method||"GET",headers:{"X-API-Key":y(),Accept:"application/json",...t.body?{"Content-Type":"application/json"}:{},...t.headers},body:t.body?JSON.stringify(t.body):void 0});if(!r.ok){let a=await r.text().catch(()=>"");throw new Error(`Plane API ${r.status}: ${a.slice(0,300)}`)}let s=await r.text().catch(()=>"");if(!s||!s.trim())return{};try{return JSON.parse(s)}catch{return{raw:s}}}var k={backlog:"todo",unstarted:"todo",started:"in_progress",completed:"done",cancelled:"done"},P=/\b(blocked|on[\s-]?hold|waiting|stuck)\b/i;function u(e){return e?e.name&&P.test(e.name)?"blocked":k[e.group]||"unknown":"unknown"}var m=new Map,S=300*1e3;async function g(e){let{workspaceSlug:t,projectId:o}=p(e),r=m.get(o);if(r&&Date.now()-r.fetchedAt<S)return r.states;let s=await d(`/workspaces/${encodeURIComponent(t)}/projects/${encodeURIComponent(o)}/states/`,{query:{per_page:100}}),a=(s.results||s||[]).map(n=>({id:n.id,name:n.name,group:n.group,color:n.color}));return m.set(o,{fetchedAt:Date.now(),states:a}),a}function l(e){return String(e||"").toLowerCase().replace(/\s+/g,"").replace(/[()\-_::"'`]/g,"")}function I(e,t){let o=l(t);if(!o)return null;let r=e.find(a=>l(a.name)===o);if(r)return r;let s={todo:["todo","backlog","open","unstarted"],inprogress:["inprogress","started","doing","wip"],done:["done","completed","closed","resolved","cancelled","canceled"],blocked:["blocked","onhold","waiting"]};for(let[,a]of Object.entries(s)){if(!a.some(i=>l(i)===o))continue;let n=o==="done"?"completed":o==="inprogress"?"started":"unstarted",c=e.find(i=>i.group===n);if(c)return c}return null}async function _(e,t){let r=(await g(t).catch(()=>[])).find(i=>i.id===e.state)||null,{workspaceSlug:s,projectId:a}=p(t),n=t.projectIdentifier&&e.sequence_id!=null?`${t.projectIdentifier}-${e.sequence_id}`:e.sequence_id!=null?String(e.sequence_id):e.id,c=e.assignees||[];return{id:e.id,key:n,title:e.name||"",body:e.description_html||e.description_stripped||e.description||"",state:r?r.name:null,stateCategory:u(r),assignee:c.length?String(c[0]):null,url:t.baseWebUrl?`${t.baseWebUrl}/${s}/projects/${a}/issues/${e.id}`:null,_raw:e}}var C={id:"plane",envKeys:["PLANE_API_KEY","PLANE_OAUTH_TOKEN","PLANE_API_URL","PLANE_WORKSPACE_SLUG","PLANE_PROJECT_ID"],planeFetch:d,toStateCategory:u,async listCandidates(e={}){let t=e.ctx||{},{workspaceSlug:o,projectId:r}=p(t),s={per_page:Math.min(Number(e.limit)||50,100),cursor:e.cursor};e.state&&(s.state=e.state),e.updatedAfter&&(s.updated_at__gte=e.updatedAfter);let n=(await d(`/workspaces/${encodeURIComponent(o)}/projects/${encodeURIComponent(r)}/work-items/`,{query:s})).results||[];return e.updatedAfter&&(n=n.filter(c=>String(c.updated_at)>String(e.updatedAfter))),Promise.all(n.map(c=>_(c,t)))},async getTicket(e,t={}){let{workspaceSlug:o,projectId:r}=p(t),s=await d(`/workspaces/${encodeURIComponent(o)}/projects/${encodeURIComponent(r)}/work-items/${encodeURIComponent(e)}/`);return!s||!s.id?null:_(s,t)},async getComments(e,t={}){let{workspaceSlug:o,projectId:r}=p(t);return((await d(`/workspaces/${encodeURIComponent(o)}/projects/${encodeURIComponent(r)}/work-items/${encodeURIComponent(e)}/comments/`,{query:{per_page:100}})).results||[]).map(n=>({id:n.id,author:n.actor||n.actor_detail?.display_name||"Unknown",body:n.comment_html||n.comment_stripped||"",createdAt:n.created_at||null,updatedAt:n.updated_at||null,_raw:n})).sort((n,c)=>String(c.createdAt).localeCompare(String(n.createdAt)))},async addComment(e,t,o={}){let{workspaceSlug:r,projectId:s}=p(o),n=/<[a-z][\s\S]*>/i.test(String(t||""))?String(t):`<p>${String(t||"")}</p>`,c=await d(`/workspaces/${encodeURIComponent(r)}/projects/${encodeURIComponent(s)}/work-items/${encodeURIComponent(e)}/comments/`,{method:"POST",body:{comment_html:n}});return{ok:!!c.id,id:c.id||null,_raw:c}},async transition(e,t,o={}){let{workspaceSlug:r,projectId:s}=p(o),a=await g(o),n=I(a,t);if(!n)return{ok:!1,error:`No Plane state matches "${t}" in this project`,availableStates:a.map(i=>({id:i.id,name:i.name,group:i.group}))};let c=await d(`/workspaces/${encodeURIComponent(r)}/projects/${encodeURIComponent(s)}/work-items/${encodeURIComponent(e)}/`,{method:"PATCH",body:{state:n.id}});return{ok:!!c.id,stateAfter:n.name,stateCategoryAfter:u(n),_raw:c}},async linkPullRequest(e,t,o,r={}){let s=o?`${o}: `:"Linked PR: ";return{ok:!!(await this.addComment(e,`<p>${s}<a href="${t}">${t}</a></p>`,r)).ok,via:"comment"}}},E=C;export{E as default,C as planeAdapter,d as planeFetch,u as toStateCategory};
@@ -147,189 +147,4 @@
147
147
  * which path was used ('remotelink' | 'attachment' | 'comment').
148
148
  */
149
149
  /** @type {StateCategory[]} */
150
- export const TRACKER_STATE_CATEGORIES: StateCategory[];
151
- /**
152
- * Normalized 5-bucket state. The pipeline branches on this; never on `state`.
153
- */
154
- export type StateCategory = "todo" | "in_progress" | "done" | "blocked" | "unknown";
155
- /**
156
- * A tracker ticket/issue projected onto the neutral model.
157
- */
158
- export type NeutralTicket = {
159
- /**
160
- * Stable provider-internal id. Jira: issue id (numeric string). Linear: uuid.
161
- * GitHub: issue number as a string. Plane: work-item uuid. Opaque — pass it
162
- * back to the same adapter; do not parse it.
163
- */
164
- id: string;
165
- /**
166
- * Human-facing reference. Jira: `PROJ-123`. Linear: `ENG-12`. GitHub:
167
- * `owner/repo#123`. Plane: `PROJ-42` (or the uuid if the identifier is
168
- * unknown). This is what shows up in PR titles / comments.
169
- */
170
- key: string;
171
- /**
172
- * Short summary line (Symphony §4 `title`).
173
- */
174
- title: string;
175
- /**
176
- * Full description as plain text / markdown (Symphony §4 `body`). ADF/HTML is
177
- * flattened by the adapter; never raw ADF or raw HTML here.
178
- */
179
- body: string;
180
- /**
181
- * RAW provider status NAME, exactly as the tracker spells it ("In Progress",
182
- * "Done", "started", "测试"). Use this for write-back (transition). `null`
183
- * when the provider/issue has no resolvable status.
184
- */
185
- state: string | null;
186
- /**
187
- * Normalized bucket — what the pipeline branches on.
188
- */
189
- stateCategory: StateCategory;
190
- /**
191
- * Single human-readable assignee (display name or login). `null` if
192
- * unassigned. Multi-assignee providers (GitHub, Plane) collapse to the first;
193
- * the full list, if any, lives in `_raw`.
194
- */
195
- assignee: string | null;
196
- /**
197
- * Canonical web URL of the ticket, or `null` if the adapter can't derive one.
198
- */
199
- url: string | null;
200
- /**
201
- * Escape hatch — the untouched provider payload. Read provider-specific data
202
- * (sprint, story points, cycle, milestone, sequence_id, labels…) from here.
203
- * NEVER promote a `_raw` field to a top-level neutral field.
204
- */
205
- _raw: any;
206
- };
207
- /**
208
- * A single comment on a ticket, projected onto the neutral model.
209
- */
210
- export type NeutralComment = {
211
- /**
212
- * Provider comment id (opaque).
213
- */
214
- id: string;
215
- /**
216
- * Human-readable author (display name/login).
217
- */
218
- author: string;
219
- /**
220
- * Comment text as plain text / markdown
221
- * (ADF/HTML flattened).
222
- */
223
- body: string;
224
- /**
225
- * ISO-8601 creation timestamp, if available.
226
- */
227
- createdAt: string | null;
228
- /**
229
- * ISO-8601 update timestamp, if available.
230
- */
231
- updatedAt: string | null;
232
- /**
233
- * Untouched provider comment payload.
234
- */
235
- _raw?: any;
236
- };
237
- /**
238
- * Options accepted by {@link TrackerAdapter.listCandidates}. Every field is
239
- * optional; what each provider honors differs (documented per adapter). The
240
- * shared minimum is "give me a bounded, newest-first slab of work to consider".
241
- */
242
- export type ListCandidatesOptions = {
243
- /**
244
- * Provider-native query. Jira: a JQL string. GitHub: free-text issue search
245
- * (or used with `labels`). Linear/Plane: ignored in favor of structured
246
- * filters below. Adapters that can't honor it ignore it.
247
- */
248
- query?: string;
249
- /**
250
- * Restrict to issues carrying label(s).
251
- */
252
- labels?: string | string[];
253
- /**
254
- * Provider state filter (raw name or, for
255
- * GitHub, open|closed|all).
256
- */
257
- state?: string;
258
- /**
259
- * ISO-8601 polling cursor; only issues
260
- * updated at/after this.
261
- */
262
- updatedAfter?: string;
263
- /**
264
- * Max tickets to return (bounded).
265
- */
266
- limit?: number;
267
- /**
268
- * Opaque pagination cursor (Plane).
269
- */
270
- cursor?: string;
271
- /**
272
- * Provider scope/context (e.g. GitHub
273
- * {owner, repo}; Plane {workspaceSlug,
274
- * projectId}). Passed through verbatim.
275
- */
276
- ctx?: any;
277
- };
278
- /**
279
- * The neutral tracker interface — the 6-method MINIMUM contract.
280
- *
281
- * Three READ methods + three WRITE methods + identity metadata. Each concrete
282
- * adapter (jira / linear / github / plane) implements exactly these. Anything a
283
- * single provider can do that the others can't does NOT get a 7th method — it
284
- * stays accessible only via that provider's own skill tools / the `_raw` hatch.
285
- */
286
- export type TrackerAdapter = {
287
- /**
288
- * Provider id: 'jira' | 'linear' | 'github' | 'plane'.
289
- */
290
- id: string;
291
- /**
292
- * READ. Return a bounded, newest-first set of tickets to consider for work.
293
- */
294
- listCandidates: (opts?: ListCandidatesOptions) => Promise<NeutralTicket[]>;
295
- /**
296
- * READ. Fetch one ticket by its `key` (or id). `null` if not found.
297
- */
298
- getTicket: (key: string, ctx?: any) => Promise<NeutralTicket | null>;
299
- /**
300
- * READ. Fetch the comment thread (newest first).
301
- */
302
- getComments: (key: string, ctx?: any) => Promise<NeutralComment[]>;
303
- /**
304
- * WRITE. Add a comment. `body` is plain text / markdown; the adapter handles
305
- * provider encoding (Jira ADF, Plane HTML).
306
- */
307
- addComment: (key: string, body: string, ctx?: any) => Promise<{
308
- ok: boolean;
309
- id?: string | null;
310
- error?: string;
311
- }>;
312
- /**
313
- * WRITE. Move the ticket to a target state, addressed by its RAW name
314
- * (fuzzy-matched per provider). Jira performs a workflow transition; Linear /
315
- * Plane PATCH the state directly; GitHub maps to open/close (+ a labels
316
- * convention — see github-adapter). NOT every target name is reachable on
317
- * every provider; the result carries `ok:false` + `error` when it isn't.
318
- */
319
- transition: (key: string, targetStateName: string, ctx?: any) => Promise<{
320
- ok: boolean;
321
- stateAfter?: string | null;
322
- stateCategoryAfter?: StateCategory;
323
- error?: string;
324
- }>;
325
- /**
326
- * WRITE. Associate a PR URL with the ticket. Native where possible (Jira
327
- * remote-link, Linear attachment); a comment everywhere else. `via` reports
328
- * which path was used ('remotelink' | 'attachment' | 'comment').
329
- */
330
- linkPullRequest: (key: string, prUrl: string, title?: string, ctx?: any) => Promise<{
331
- ok: boolean;
332
- via?: string;
333
- error?: string;
334
- }>;
335
- };
150
+ export declare const TRACKER_STATE_CATEGORIES: string[];
@@ -1,42 +1,26 @@
1
- export namespace triggerAgentSkill {
2
- let id: string;
3
- let serverName: string;
4
- let allowedTools: string[];
5
- let envKeys: any[];
6
- let description: string;
7
- let promptFragment: string;
8
- function resolve(): {
9
- command: any;
10
- args: any[];
11
- env: {};
12
- description: string;
13
- type?: undefined;
14
- alwaysLoad?: undefined;
15
- } | {
16
- type: string;
17
- command: string;
18
- args: any[];
19
- env: {};
20
- description: string;
21
- alwaysLoad: boolean;
22
- };
23
- function handleToolCall(name: any, args?: {}): Promise<string>;
24
- let tools: {
25
- name: string;
26
- description: string;
27
- input_schema: {
28
- type: string;
29
- properties: {
30
- workflowType: {
31
- type: string;
32
- description: string;
33
- };
34
- input: {
35
- type: string;
36
- description: string;
37
- };
38
- };
39
- required: any[];
40
- };
41
- }[];
42
- }
1
+ /**
2
+ * trigger-agent — a GENERIC, agent-callable skill for firing another Zibby
3
+ * agent run from inside a running agent.
4
+ *
5
+ * The agent gets ONE real MCP tool, `trigger_agent`, and DECIDES for itself
6
+ * when (and how many times) to call it — so a triage agent can trigger a fix for
7
+ * every issue it judges worth fixing, an orchestrator can fan out to N children,
8
+ * etc. This is the agent-driven counterpart to the engine's deterministic
9
+ * `dispatchSubgraph` — the primitive lives in the model's hands, not in node code.
10
+ *
11
+ * Portable across CLOUD and SELF-HOSTED (the same reason @zibby/skills/datasetStore
12
+ * works in both): it POSTs to `${apiBase}/projects/{PROJECT_ID}/workflows/{type}/trigger`
13
+ * with the run's `PROJECT_API_TOKEN`, resolving `apiBase` from the env the runtime
14
+ * injects — cloud sets `PROGRESS_API_URL` (`<base>/executions`), self-hosted's
15
+ * docker/k8s dispatcher sets `ZIBBY_ACCOUNT_API_URL` ("reachable FROM the run") —
16
+ * so neither environment needs a special case.
17
+ *
18
+ * Fire-and-forget: it triggers the run and returns its executionId; it does NOT
19
+ * wait for the child to finish. `handleToolCall` NEVER throws — any failure comes
20
+ * back as `{ ok:false, error }` so a bad trigger can't crash the calling agent.
21
+ *
22
+ * Shape mirrors the other hand-written multi-tool skills (github.js / datasetStore.js):
23
+ * `serverName`, `allowedTools`, `tools[]`, `handleToolCall`, and a `resolve()` that
24
+ * spawns the generic bin/mcp-skill.mjs.
25
+ */
26
+ export declare const triggerAgentSkill: any;
@@ -1 +1 @@
1
- import{dirname as f,resolve as d}from"path";import{fileURLToPath as u}from"url";import{existsSync as h}from"fs";function T(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let r=f(u(import.meta.url)),e=d(r,"..","bin","mcp-skill.mjs");return h(e)?e:null}function _(){return process.env.PROJECT_API_TOKEN||process.env.ZIBBY_USER_TOKEN||null}function w(){return((process.env.PROGRESS_API_URL||"").replace(/\/executions\/?$/,"")||process.env.ZIBBY_ACCOUNT_API_URL||process.env.ZIBBY_PROD_ACCOUNT_API_URL||(process.env.ZIBBY_ENV==="local"?"http://localhost:3001":"https://api-prod.zibby.app")).replace(/\/+$/,"")}var y={name:"trigger_agent",description:"Trigger another Zibby workflow/agent run in THIS project (fire-and-forget). Call it once per run you want to start \u2014 the agent decides which and how many. Omit workflowType to re-run THIS same agent (self-dispatch, e.g. with a different trigger input). Returns the started run's executionId; does NOT wait for it to finish.",input_schema:{type:"object",properties:{workflowType:{type:"string",description:"Which workflow to trigger (its type/slug in this project). Omit to trigger THIS same agent (self-dispatch)."},input:{type:"object",description:"The trigger payload passed to the target workflow (validated against its state schema)."}},required:[]}},k={id:"trigger-agent",serverName:"trigger",allowedTools:["mcp__trigger__*"],envKeys:[],description:"Trigger another Zibby workflow/agent run in this project (agent-driven, fire-and-forget; cloud + self-hosted).",promptFragment:"## Trigger another agent (agent-driven)\nYou can start another Zibby agent run yourself with the `trigger_agent`\ntool \u2014 and YOU decide when and how many times to call it. Each call starts ONE\nindependent run (fire-and-forget) and returns its executionId; it does NOT wait for\nthat run to finish.\n- To re-run THIS same agent (self-dispatch) \u2014 e.g. to hand an item to another of\n this agent's scenarios \u2014 OMIT `workflowType` and pass the `input` for that run.\n- To trigger a DIFFERENT agent in the project, pass its `workflowType` + `input`.\nCall it once per run you want to start (loop over your items and call it for each).\nIt never throws \u2014 a failure comes back as { ok:false, error }; log it and move on.",resolve(){let r=T();if(!r)return{command:null,args:[],env:{},description:this.description};let e={};for(let t of["PROJECT_API_TOKEN","PROJECT_ID","WORKFLOW_TYPE","PROGRESS_API_URL","ZIBBY_ACCOUNT_API_URL","ZIBBY_PROD_ACCOUNT_API_URL","ZIBBY_ENV","ZIBBY_USER_TOKEN"])process.env[t]&&(e[t]=process.env[t]);return{type:"stdio",command:"node",args:[r,"../dist/triggerAgent.js","triggerAgentSkill"],env:e,description:this.description,alwaysLoad:!1}},async handleToolCall(r,e={}){if(r!=="trigger_agent")return JSON.stringify({ok:!1,error:`unknown tool: ${r}`});try{let t=process.env.PROJECT_ID,a=_(),s=typeof e.workflowType=="string"&&e.workflowType.trim()?e.workflowType.trim():(process.env.WORKFLOW_TYPE||"").trim();if(!t)return JSON.stringify({ok:!1,error:"PROJECT_ID not set \u2014 cannot resolve the target project."});if(!a)return JSON.stringify({ok:!1,error:"PROJECT_API_TOKEN not set \u2014 cannot authenticate the trigger."});if(!s)return JSON.stringify({ok:!1,error:"No workflowType given and WORKFLOW_TYPE is unset \u2014 nothing to trigger."});let l=`${w()}/projects/${encodeURIComponent(t)}/workflows/${encodeURIComponent(s)}/trigger`,c=new AbortController,g=setTimeout(()=>c.abort(),2e4),n;try{n=await fetch(l,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${a}`},body:JSON.stringify({input:e.input&&typeof e.input=="object"?e.input:{}}),signal:c.signal})}finally{clearTimeout(g)}let i=await n.text().catch(()=>""),o;try{o=i?JSON.parse(i):{}}catch{o={raw:i}}if(!n.ok)return JSON.stringify({ok:!1,error:`trigger failed (HTTP ${n.status})`,detail:o&&(o.error||o.message)||i.slice(0,300)});let p=o.executionId||o.execution?.id||o.id||null;return JSON.stringify({ok:!0,workflowType:s,executionId:p,note:"run started (fire-and-forget)"})}catch(t){return JSON.stringify({ok:!1,error:`trigger_agent failed: ${t?.message||String(t)}`})}},tools:[y]};export{k as triggerAgentSkill};
1
+ import{dirname as f,resolve as d}from"path";import{fileURLToPath as u}from"url";import{existsSync as h}from"fs";function T(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let r=f(u(import.meta.url)),e=d(r,"..","bin","mcp-skill.mjs");return h(e)?e:null}function y(){return process.env.PROJECT_API_TOKEN||process.env.ZIBBY_USER_TOKEN||null}function _(){return((process.env.PROGRESS_API_URL||"").replace(/\/executions\/?$/,"")||process.env.ZIBBY_ACCOUNT_API_URL||process.env.ZIBBY_PROD_ACCOUNT_API_URL||(process.env.ZIBBY_ENV==="local"?"http://localhost:3001":"https://api-prod.zibby.app")).replace(/\/+$/,"")}var w={name:"trigger_agent",description:"Trigger another Zibby workflow/agent run in THIS project (fire-and-forget). Call it once per run you want to start \u2014 the agent decides which and how many. Omit workflowType to re-run THIS same agent (self-dispatch, e.g. with a different trigger input). Returns the started run's executionId; does NOT wait for it to finish.",input_schema:{type:"object",properties:{workflowType:{type:"string",description:"Which workflow to trigger (its type/slug in this project). Omit to trigger THIS same agent (self-dispatch)."},input:{type:"object",description:"The trigger payload passed to the target workflow (validated against its state schema)."}},required:[]}},k={id:"trigger-agent",serverName:"trigger",allowedTools:["mcp__trigger__*"],envKeys:[],description:"Trigger another Zibby workflow/agent run in this project (agent-driven, fire-and-forget; cloud + self-hosted).",promptFragment:"## Trigger another agent (agent-driven)\nYou can start another Zibby agent run yourself with the `trigger_agent`\ntool \u2014 and YOU decide when and how many times to call it. Each call starts ONE\nindependent run (fire-and-forget) and returns its executionId; it does NOT wait for\nthat run to finish.\n- To re-run THIS same agent (self-dispatch) \u2014 e.g. to hand an item to another of\n this agent's scenarios \u2014 OMIT `workflowType` and pass the `input` for that run.\n- To trigger a DIFFERENT agent in the project, pass its `workflowType` + `input`.\nCall it once per run you want to start (loop over your items and call it for each).\nIt never throws \u2014 a failure comes back as { ok:false, error }; log it and move on.",resolve(){let r=T();if(!r)return{command:null,args:[],env:{},description:this.description};let e={};for(let t of["PROJECT_API_TOKEN","PROJECT_ID","WORKFLOW_TYPE","PROGRESS_API_URL","ZIBBY_ACCOUNT_API_URL","ZIBBY_PROD_ACCOUNT_API_URL","ZIBBY_ENV","ZIBBY_USER_TOKEN"])process.env[t]&&(e[t]=process.env[t]);return{type:"stdio",command:"node",args:[r,"../dist/triggerAgent.js","triggerAgentSkill"],env:e,description:this.description,alwaysLoad:!1}},async handleToolCall(r,e={}){if(r!=="trigger_agent")return JSON.stringify({ok:!1,error:`unknown tool: ${r}`});try{let t=process.env.PROJECT_ID,a=y(),s=typeof e.workflowType=="string"&&e.workflowType.trim()?e.workflowType.trim():(process.env.WORKFLOW_TYPE||"").trim();if(!t)return JSON.stringify({ok:!1,error:"PROJECT_ID not set \u2014 cannot resolve the target project."});if(!a)return JSON.stringify({ok:!1,error:"PROJECT_API_TOKEN not set \u2014 cannot authenticate the trigger."});if(!s)return JSON.stringify({ok:!1,error:"No workflowType given and WORKFLOW_TYPE is unset \u2014 nothing to trigger."});let l=`${_()}/projects/${encodeURIComponent(t)}/workflows/${encodeURIComponent(s)}/trigger`,c=new AbortController,g=setTimeout(()=>c.abort(),2e4),n;try{n=await fetch(l,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${a}`},body:JSON.stringify({input:e.input&&typeof e.input=="object"?e.input:{}}),signal:c.signal})}finally{clearTimeout(g)}let i=await n.text().catch(()=>""),o;try{o=i?JSON.parse(i):{}}catch{o={raw:i}}if(!n.ok)return JSON.stringify({ok:!1,error:`trigger failed (HTTP ${n.status})`,detail:o&&(o.error||o.message)||i.slice(0,300)});let p=o.executionId||o.execution?.id||o.id||null;return JSON.stringify({ok:!0,workflowType:s,executionId:p,note:"run started (fire-and-forget)"})}catch(t){return JSON.stringify({ok:!1,error:`trigger_agent failed: ${t?.message||String(t)}`})}},tools:[w]};export{k as triggerAgentSkill};