heyhank 0.1.0 → 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.
Files changed (161) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -10
  3. package/bin/cli.ts +7 -7
  4. package/bin/ctl.ts +42 -42
  5. package/dist/assets/{AgentsPage-BPhirnCe.js → AgentsPage-DqjDAcIw.js} +3 -3
  6. package/dist/assets/AssistantPage-C50CQFSB.js +2 -0
  7. package/dist/assets/BusinessPage-AY70tf1k.js +1 -0
  8. package/dist/assets/{CronManager-DDbz-yiT.js → CronManager-Dt7LLuRr.js} +1 -1
  9. package/dist/assets/HelpPage-tlGx7fQF.js +1 -0
  10. package/dist/assets/{IntegrationsPage-CrOitCmJ.js → IntegrationsPage-B4XOuHXu.js} +1 -1
  11. package/dist/assets/JarvisHUD-BDvuRd0I.js +120 -0
  12. package/dist/assets/MediaPage-CofV9Rd-.js +1 -0
  13. package/dist/assets/MemoryPage-Cj7FeqmJ.js +1 -0
  14. package/dist/assets/{PlatformDashboard-Do6F0O2p.js → PlatformDashboard-B9kXAlH1.js} +1 -1
  15. package/dist/assets/{Playground-Fc5cdc5p.js → Playground-Cka-pRkP.js} +1 -1
  16. package/dist/assets/{ProcessPanel-CslEiZkI.js → ProcessPanel-BqhQgfYj.js} +1 -1
  17. package/dist/assets/{PromptsPage-D2EhsdNO.js → PromptsPage-VveKc9uX.js} +2 -2
  18. package/dist/assets/RunsPage-DXVEk0AZ.js +1 -0
  19. package/dist/assets/{SandboxManager-a1AVI5q2.js → SandboxManager-DACcwfDF.js} +1 -1
  20. package/dist/assets/SettingsPage-jfuQh8Tu.js +51 -0
  21. package/dist/assets/SkillsMarketplace-DrigiApe.js +1 -0
  22. package/dist/assets/SocialMediaPage-DOh3IPe8.js +10 -0
  23. package/dist/assets/{TailscalePage-CHiFhZXF.js → TailscalePage-DLhJWATT.js} +1 -1
  24. package/dist/assets/TelephonyPage-9C4C3_ot.js +9 -0
  25. package/dist/assets/{TerminalPage-Drwyrnfd.js → TerminalPage-ChX-8Wu7.js} +1 -1
  26. package/dist/assets/{gemini-live-client-C7rqAW7G.js → gemini-live-client-C70FEtX2.js} +11 -8
  27. package/dist/assets/index-C6Q5UQHD.js +229 -0
  28. package/dist/assets/index-ZxGXgiV3.css +32 -0
  29. package/dist/assets/sw-register-BBYuk-kw.js +1 -0
  30. package/dist/assets/text-chat-client-BSbLJerZ.js +2 -0
  31. package/dist/assets/workbox-window.prod.es5-BBnX5xw4.js +2 -0
  32. package/dist/index.html +2 -2
  33. package/dist/sw.js +1 -1
  34. package/dist/{workbox-d2a0910a.js → workbox-080c8b91.js} +1 -1
  35. package/package.json +6 -1
  36. package/server/agent-executor.ts +102 -2
  37. package/server/agent-store.ts +3 -3
  38. package/server/agent-types.ts +11 -0
  39. package/server/assistant-store.ts +232 -6
  40. package/server/auth-manager.ts +9 -0
  41. package/server/cache-headers.ts +1 -1
  42. package/server/calendar-service.ts +10 -0
  43. package/server/ceo/document-store.ts +129 -0
  44. package/server/ceo/finance-store.ts +343 -0
  45. package/server/ceo/kpi-store.ts +208 -0
  46. package/server/ceo/memory-import.ts +277 -0
  47. package/server/ceo/news-store.ts +208 -0
  48. package/server/ceo/template-store.ts +134 -0
  49. package/server/ceo/time-tracking-store.ts +227 -0
  50. package/server/claude-auth-monitor.ts +128 -0
  51. package/server/claude-code-worker.ts +86 -0
  52. package/server/claude-session-discovery.ts +74 -1
  53. package/server/cli-launcher.ts +32 -10
  54. package/server/codex-adapter.ts +2 -2
  55. package/server/codex-ws-proxy.cjs +1 -1
  56. package/server/container-manager.ts +4 -4
  57. package/server/content-intelligence/content-engine.ts +1112 -0
  58. package/server/content-intelligence/platform-knowledge.ts +870 -0
  59. package/server/cron-store.ts +3 -3
  60. package/server/embedding-service.ts +49 -0
  61. package/server/event-bus-types.ts +13 -0
  62. package/server/execution-store.ts +54 -1
  63. package/server/federation/node-store.ts +5 -4
  64. package/server/fs-utils.ts +28 -1
  65. package/server/hank-notifications-store.ts +91 -0
  66. package/server/hank-tool-executor.ts +1835 -0
  67. package/server/hank-tools.ts +2107 -0
  68. package/server/image-pull-manager.ts +2 -2
  69. package/server/index.ts +25 -2
  70. package/server/llm-providers-streaming.ts +541 -0
  71. package/server/llm-providers.ts +12 -0
  72. package/server/marketplace.ts +249 -0
  73. package/server/mcp-registry.ts +158 -0
  74. package/server/memory-service.ts +296 -0
  75. package/server/obsidian-sync.ts +184 -0
  76. package/server/provider-manager.ts +5 -2
  77. package/server/provider-registry.ts +12 -0
  78. package/server/reminder-scheduler.ts +37 -1
  79. package/server/routes/agent-routes.ts +44 -1
  80. package/server/routes/assistant-routes.ts +198 -5
  81. package/server/routes/ceo-finance-kpi-routes.ts +167 -0
  82. package/server/routes/ceo-news-time-routes.ts +137 -0
  83. package/server/routes/ceo-routes.ts +99 -0
  84. package/server/routes/content-routes.ts +116 -0
  85. package/server/routes/email-routes.ts +147 -0
  86. package/server/routes/env-routes.ts +3 -3
  87. package/server/routes/fs-routes.ts +12 -9
  88. package/server/routes/hank-chat-routes.ts +592 -0
  89. package/server/routes/llm-routes.ts +12 -0
  90. package/server/routes/marketplace-routes.ts +63 -0
  91. package/server/routes/media-routes.ts +1 -1
  92. package/server/routes/memory-routes.ts +127 -0
  93. package/server/routes/platform-routes.ts +14 -675
  94. package/server/routes/sandbox-routes.ts +1 -1
  95. package/server/routes/settings-routes.ts +51 -1
  96. package/server/routes/socialmedia-routes.ts +152 -2
  97. package/server/routes/system-routes.ts +2 -2
  98. package/server/routes/team-routes.ts +71 -0
  99. package/server/routes/telephony-routes.ts +98 -18
  100. package/server/routes.ts +36 -9
  101. package/server/session-creation-service.ts +2 -2
  102. package/server/session-orchestrator.ts +54 -2
  103. package/server/session-types.ts +2 -0
  104. package/server/settings-manager.ts +50 -2
  105. package/server/skill-discovery.ts +68 -0
  106. package/server/socialmedia/adapters/browser-adapter.ts +179 -0
  107. package/server/socialmedia/adapters/postiz-adapter.ts +291 -14
  108. package/server/socialmedia/manager.ts +234 -15
  109. package/server/socialmedia/store.ts +51 -1
  110. package/server/socialmedia/types.ts +35 -2
  111. package/server/socialview/browser-manager.ts +150 -0
  112. package/server/socialview/extractors.ts +1298 -0
  113. package/server/socialview/image-describe.ts +188 -0
  114. package/server/socialview/library.ts +119 -0
  115. package/server/socialview/poster.ts +276 -0
  116. package/server/socialview/routes.ts +371 -0
  117. package/server/socialview/style-analyzer.ts +187 -0
  118. package/server/socialview/style-profiles.ts +67 -0
  119. package/server/socialview/types.ts +166 -0
  120. package/server/socialview/vision.ts +127 -0
  121. package/server/socialview/vnc-manager.ts +110 -0
  122. package/server/style-injector.ts +135 -0
  123. package/server/team-service.ts +239 -0
  124. package/server/team-store.ts +75 -0
  125. package/server/team-types.ts +52 -0
  126. package/server/telephony/audio-bridge.ts +281 -35
  127. package/server/telephony/audio-recorder.ts +132 -0
  128. package/server/telephony/call-manager.ts +803 -104
  129. package/server/telephony/call-types.ts +67 -1
  130. package/server/telephony/esl-client.ts +319 -0
  131. package/server/telephony/freeswitch-sync.ts +155 -0
  132. package/server/telephony/phone-utils.ts +63 -0
  133. package/server/telephony/telephony-store.ts +9 -8
  134. package/server/url-validator.ts +82 -0
  135. package/server/vault-markdown.ts +317 -0
  136. package/server/vault-migration.ts +121 -0
  137. package/server/vault-store.ts +466 -0
  138. package/server/vault-watcher.ts +59 -0
  139. package/server/vector-store.ts +210 -0
  140. package/server/voice-pipeline/gemini-live-adapter.ts +97 -0
  141. package/server/voice-pipeline/greeting-cache.ts +200 -0
  142. package/server/voice-pipeline/manager.ts +249 -0
  143. package/server/voice-pipeline/pipeline.ts +335 -0
  144. package/server/voice-pipeline/providers/index.ts +47 -0
  145. package/server/voice-pipeline/providers/llm-internal.ts +527 -0
  146. package/server/voice-pipeline/providers/stt-google.ts +157 -0
  147. package/server/voice-pipeline/providers/tts-google.ts +126 -0
  148. package/server/voice-pipeline/types.ts +247 -0
  149. package/server/ws-bridge-types.ts +6 -1
  150. package/dist/assets/AssistantPage-DJ-cMQfb.js +0 -1
  151. package/dist/assets/HelpPage-DMfkzERp.js +0 -1
  152. package/dist/assets/MediaPage-CE5rdvkC.js +0 -1
  153. package/dist/assets/RunsPage-C5BZF5Rx.js +0 -1
  154. package/dist/assets/SettingsPage-DirhjQrJ.js +0 -51
  155. package/dist/assets/SocialMediaPage-DBuM28vD.js +0 -1
  156. package/dist/assets/TelephonyPage-x0VV0fOo.js +0 -1
  157. package/dist/assets/index-C8M_PUmX.css +0 -32
  158. package/dist/assets/index-CEqZnThB.js +0 -204
  159. package/dist/assets/sw-register-LSSpj6RU.js +0 -1
  160. package/dist/assets/workbox-window.prod.es5-BIl4cyR9.js +0 -2
  161. package/server/socialmedia/adapters/ayrshare-adapter.ts +0 -169
@@ -1 +0,0 @@
1
- import{_ as f}from"./index-CEqZnThB.js";function h(s={}){const{immediate:t=!1,onNeedRefresh:a,onOfflineReady:i,onRegistered:n,onRegisteredSW:r,onRegisterError:o}=s;let c,l;const p=async(e=!0)=>{await l};async function d(){if("serviceWorker"in navigator){if(c=await f(async()=>{const{Workbox:e}=await import("./workbox-window.prod.es5-BIl4cyR9.js");return{Workbox:e}},[]).then(({Workbox:e})=>new e("/sw.js",{scope:"/",type:"classic"})).catch(e=>{o==null||o(e)}),!c)return;c.addEventListener("activated",e=>{(e.isUpdate||e.isExternal)&&window.location.reload()}),c.addEventListener("installed",e=>{e.isUpdate||i==null||i()}),c.register({immediate:t}).then(e=>{r?r("/sw.js",e):n==null||n(e)}).catch(e=>{o==null||o(e)})}}return l=d(),p}let u;h({onRegisteredSW(s,t){u=t,t&&setInterval(()=>{t.update()},3600*1e3)},onOfflineReady(){console.log("[SW] Offline-ready: all assets precached")}});function b(s){const t="=".repeat((4-s.length%4)%4),a=(s+t).replace(/-/g,"+").replace(/_/g,"/"),i=atob(a),n=new Uint8Array(i.length);for(let r=0;r<i.length;r++)n[r]=i.charCodeAt(r);return n}async function w(){var o;const s=u??await((o=navigator.serviceWorker)==null?void 0:o.ready);if(!s)return console.warn("[push] No service worker registration available"),null;const t=await s.pushManager.getSubscription();if(t)return console.log("[push] Already subscribed to push notifications"),t;const a=await fetch("/api/push/vapid-key");if(!a.ok)return console.error("[push] Failed to fetch VAPID key:",a.status),null;const{publicKey:i}=await a.json(),n=await s.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:b(i)}),r=await fetch("/api/push/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({subscription:n.toJSON()})});return r.ok?console.log("[push] Successfully subscribed to push notifications"):console.error("[push] Failed to send subscription to server:",r.status),n}async function y(){var i;const s=u??await((i=navigator.serviceWorker)==null?void 0:i.ready);if(!s)return!1;const t=await s.pushManager.getSubscription();if(!t)return!0;const a=await t.unsubscribe();return a&&console.log("[push] Successfully unsubscribed from push notifications"),a}export{w as subscribeToPush,y as unsubscribeFromPush};
@@ -1,2 +0,0 @@
1
- try{self["workbox:window:7.3.0"]&&_()}catch{}function b(n,r){return new Promise((function(t){var o=new MessageChannel;o.port1.onmessage=function(f){t(f.data)},n.postMessage(r,[o.port2])}))}function P(n,r){(r==null||r>n.length)&&(r=n.length);for(var t=0,o=Array(r);t<r;t++)o[t]=n[t];return o}function j(n,r){for(var t=0;t<r.length;t++){var o=r[t];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(n,W(o.key),o)}}function S(n,r){var t=typeof Symbol<"u"&&n[Symbol.iterator]||n["@@iterator"];if(t)return(t=t.call(n)).next.bind(t);if(Array.isArray(n)||(t=(function(f,c){if(f){if(typeof f=="string")return P(f,c);var a={}.toString.call(f).slice(8,-1);return a==="Object"&&f.constructor&&(a=f.constructor.name),a==="Map"||a==="Set"?Array.from(f):a==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?P(f,c):void 0}})(n))||r){t&&(n=t);var o=0;return function(){return o>=n.length?{done:!0}:{done:!1,value:n[o++]}}}throw new TypeError(`Invalid attempt to iterate non-iterable instance.
2
- In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function w(n,r){return w=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,o){return t.__proto__=o,t},w(n,r)}function W(n){var r=(function(t,o){if(typeof t!="object"||!t)return t;var f=t[Symbol.toPrimitive];if(f!==void 0){var c=f.call(t,o);if(typeof c!="object")return c;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)})(n,"string");return typeof r=="symbol"?r:r+""}try{self["workbox:core:7.3.0"]&&_()}catch{}var m=function(){var n=this;this.promise=new Promise((function(r,t){n.resolve=r,n.reject=t}))};function y(n,r){var t=location.href;return new URL(n,t).href===new URL(r,t).href}var d=function(n,r){this.type=n,Object.assign(this,r)};function l(n,r,t){return t?r?r(n):n:(n&&n.then||(n=Promise.resolve(n)),r?n.then(r):n)}function k(){}var L={type:"SKIP_WAITING"};function E(n,r){return n&&n.then?n.then(k):Promise.resolve()}var O=(function(n){function r(c,a){var e,i;return a===void 0&&(a={}),(e=n.call(this)||this).nn={},e.tn=0,e.rn=new m,e.en=new m,e.on=new m,e.un=0,e.an=new Set,e.cn=function(){var u=e.fn,s=u.installing;e.tn>0||!y(s.scriptURL,e.sn.toString())||performance.now()>e.un+6e4?(e.vn=s,u.removeEventListener("updatefound",e.cn)):(e.hn=s,e.an.add(s),e.rn.resolve(s)),++e.tn,s.addEventListener("statechange",e.ln)},e.ln=function(u){var s=e.fn,v=u.target,h=v.state,p=v===e.vn,g={sw:v,isExternal:p,originalEvent:u};!p&&e.mn&&(g.isUpdate=!0),e.dispatchEvent(new d(h,g)),h==="installed"?e.wn=self.setTimeout((function(){h==="installed"&&s.waiting===v&&e.dispatchEvent(new d("waiting",g))}),200):h==="activating"&&(clearTimeout(e.wn),p||e.en.resolve(v))},e.yn=function(u){var s=e.hn,v=s!==navigator.serviceWorker.controller;e.dispatchEvent(new d("controlling",{isExternal:v,originalEvent:u,sw:s,isUpdate:e.mn})),v||e.on.resolve(s)},e.gn=(i=function(u){var s=u.data,v=u.ports,h=u.source;return l(e.getSW(),(function(){e.an.has(h)&&e.dispatchEvent(new d("message",{data:s,originalEvent:u,ports:v,sw:h}))}))},function(){for(var u=[],s=0;s<arguments.length;s++)u[s]=arguments[s];try{return Promise.resolve(i.apply(this,u))}catch(v){return Promise.reject(v)}}),e.sn=c,e.nn=a,navigator.serviceWorker.addEventListener("message",e.gn),e}var t,o;o=n,(t=r).prototype=Object.create(o.prototype),t.prototype.constructor=t,w(t,o);var f=r.prototype;return f.register=function(c){var a=(c===void 0?{}:c).immediate,e=a!==void 0&&a;try{var i=this;return l((function(u,s){var v=u();return v&&v.then?v.then(s):s(v)})((function(){if(!e&&document.readyState!=="complete")return E(new Promise((function(u){return window.addEventListener("load",u)})))}),(function(){return i.mn=!!navigator.serviceWorker.controller,i.dn=i.pn(),l(i.bn(),(function(u){i.fn=u,i.dn&&(i.hn=i.dn,i.en.resolve(i.dn),i.on.resolve(i.dn),i.dn.addEventListener("statechange",i.ln,{once:!0}));var s=i.fn.waiting;return s&&y(s.scriptURL,i.sn.toString())&&(i.hn=s,Promise.resolve().then((function(){i.dispatchEvent(new d("waiting",{sw:s,wasWaitingBeforeRegister:!0}))})).then((function(){}))),i.hn&&(i.rn.resolve(i.hn),i.an.add(i.hn)),i.fn.addEventListener("updatefound",i.cn),navigator.serviceWorker.addEventListener("controllerchange",i.yn),i.fn}))})))}catch(u){return Promise.reject(u)}},f.update=function(){try{return this.fn?l(E(this.fn.update())):l()}catch(c){return Promise.reject(c)}},f.getSW=function(){return this.hn!==void 0?Promise.resolve(this.hn):this.rn.promise},f.messageSW=function(c){try{return l(this.getSW(),(function(a){return b(a,c)}))}catch(a){return Promise.reject(a)}},f.messageSkipWaiting=function(){this.fn&&this.fn.waiting&&b(this.fn.waiting,L)},f.pn=function(){var c=navigator.serviceWorker.controller;return c&&y(c.scriptURL,this.sn.toString())?c:void 0},f.bn=function(){try{var c=this;return l((function(a,e){try{var i=a()}catch(u){return e(u)}return i&&i.then?i.then(void 0,e):i})((function(){return l(navigator.serviceWorker.register(c.sn,c.nn),(function(a){return c.un=performance.now(),a}))}),(function(a){throw a})))}catch(a){return Promise.reject(a)}},(function(c,a,e){return a&&j(c.prototype,a),Object.defineProperty(c,"prototype",{writable:!1}),c})(r,[{key:"active",get:function(){return this.en.promise}},{key:"controlling",get:function(){return this.on.promise}}])})((function(){function n(){this.Pn=new Map}var r=n.prototype;return r.addEventListener=function(t,o){this.jn(t).add(o)},r.removeEventListener=function(t,o){this.jn(t).delete(o)},r.dispatchEvent=function(t){t.target=this;for(var o,f=S(this.jn(t.type));!(o=f()).done;)(0,o.value)(t)},r.jn=function(t){return this.Pn.has(t)||this.Pn.set(t,new Set),this.Pn.get(t)},n})());export{O as Workbox,d as WorkboxEvent,b as messageSW};
@@ -1,169 +0,0 @@
1
- // ─── Ayrshare Adapter ────────────────────────────────────────────────────────
2
- // REST client for Ayrshare social media API.
3
-
4
- import type { SocialMediaAdapter } from "../adapter.js";
5
- import type { SocialProfile, CreatePostInput, PostAnalytics, AccountAnalytics, SocialComment, SocialPlatform } from "../types.js";
6
-
7
- const BASE_URL = "https://app.ayrshare.com/api";
8
-
9
- export class AyrshareAdapter implements SocialMediaAdapter {
10
- private apiKey: string;
11
-
12
- constructor(config: { apiKey: string }) {
13
- this.apiKey = config.apiKey;
14
- }
15
-
16
- private headers(): Record<string, string> {
17
- return {
18
- "Content-Type": "application/json",
19
- "Authorization": `Bearer ${this.apiKey}`,
20
- };
21
- }
22
-
23
- async testConnection(): Promise<{ ok: boolean; error?: string; data?: unknown }> {
24
- try {
25
- const res = await fetch(`${BASE_URL}/user`, { headers: this.headers() });
26
- if (!res.ok) {
27
- return { ok: false, error: `Ayrshare returned ${res.status}: ${res.statusText}` };
28
- }
29
- const data = await res.json();
30
- return { ok: true, data };
31
- } catch (err: any) {
32
- return { ok: false, error: err?.message ?? "Connection failed" };
33
- }
34
- }
35
-
36
- async getProfiles(): Promise<SocialProfile[]> {
37
- try {
38
- const res = await fetch(`${BASE_URL}/user`, { headers: this.headers() });
39
- if (!res.ok) return [];
40
- const data = await res.json();
41
- const accounts: string[] = data.activeSocialAccounts ?? [];
42
- return accounts.map((platform) => ({
43
- id: platform,
44
- platform: platform as SocialPlatform,
45
- name: data.displayNames?.[platform] ?? platform,
46
- picture: null,
47
- }));
48
- } catch {
49
- return [];
50
- }
51
- }
52
-
53
- supportedPlatforms(): SocialPlatform[] {
54
- return ["twitter", "instagram", "linkedin", "facebook", "tiktok", "threads"];
55
- }
56
-
57
- async createPost(input: CreatePostInput): Promise<{ id: string | null; status: string; backendData?: unknown }> {
58
- try {
59
- const body: any = {
60
- post: input.text,
61
- platforms: input.platforms,
62
- };
63
- if (input.scheduledAt) {
64
- body.scheduleDate = input.scheduledAt;
65
- }
66
- if (input.mediaUrls?.length) {
67
- body.mediaUrls = input.mediaUrls;
68
- }
69
-
70
- const res = await fetch(`${BASE_URL}/post`, {
71
- method: "POST",
72
- headers: this.headers(),
73
- body: JSON.stringify(body),
74
- });
75
- const data = await res.json();
76
- if (!res.ok || data.status === "error") {
77
- return { id: null, status: "failed", backendData: data };
78
- }
79
- return {
80
- id: data.id ?? null,
81
- status: data.scheduleDate ? "scheduled" : "published",
82
- backendData: data,
83
- };
84
- } catch (err: any) {
85
- return { id: null, status: "failed", backendData: { error: err?.message } };
86
- }
87
- }
88
-
89
- async listPosts(opts?: { limit?: number }): Promise<Array<{ id: string; text: string; status: string; platforms: string[]; createdAt?: string | null; scheduledAt?: string | null }>> {
90
- try {
91
- const res = await fetch(`${BASE_URL}/history`, { headers: this.headers() });
92
- if (!res.ok) return [];
93
- const data = await res.json();
94
- const posts = Array.isArray(data) ? data : [];
95
- return posts.slice(0, opts?.limit ?? 50).map((p: any) => ({
96
- id: p.id ?? "",
97
- text: p.post ?? p.text ?? "",
98
- status: p.status ?? "unknown",
99
- platforms: p.platforms ?? [],
100
- createdAt: p.created ?? p.createdAt ?? null,
101
- scheduledAt: p.scheduleDate ?? null,
102
- }));
103
- } catch {
104
- return [];
105
- }
106
- }
107
-
108
- async deletePost(postId: string): Promise<boolean> {
109
- try {
110
- const res = await fetch(`${BASE_URL}/post`, {
111
- method: "DELETE",
112
- headers: this.headers(),
113
- body: JSON.stringify({ id: postId }),
114
- });
115
- return res.ok;
116
- } catch {
117
- return false;
118
- }
119
- }
120
-
121
- async getAnalytics(postId: string): Promise<PostAnalytics> {
122
- try {
123
- const res = await fetch(`${BASE_URL}/analytics/post`, {
124
- method: "POST",
125
- headers: this.headers(),
126
- body: JSON.stringify({ id: postId }),
127
- });
128
- if (!res.ok) return { impressions: 0, likes: 0, shares: 0, comments: 0 };
129
- const data = await res.json();
130
- return {
131
- impressions: data.impressions ?? 0,
132
- likes: data.likes ?? data.engagements?.likes ?? 0,
133
- shares: data.shares ?? data.engagements?.shares ?? 0,
134
- comments: data.comments ?? data.engagements?.comments ?? 0,
135
- };
136
- } catch {
137
- return { impressions: 0, likes: 0, shares: 0, comments: 0 };
138
- }
139
- }
140
-
141
- async getAccountAnalytics(profileId: string): Promise<AccountAnalytics> {
142
- try {
143
- const res = await fetch(`${BASE_URL}/analytics/social`, {
144
- method: "POST",
145
- headers: this.headers(),
146
- body: JSON.stringify({ platforms: [profileId] }),
147
- });
148
- if (!res.ok) return { followers: 0, following: 0, posts: 0 };
149
- const data = await res.json();
150
- const analytics = data?.[profileId] ?? data;
151
- return {
152
- followers: analytics.followers ?? 0,
153
- following: analytics.following ?? 0,
154
- posts: analytics.posts ?? 0,
155
- };
156
- } catch {
157
- return { followers: 0, following: 0, posts: 0 };
158
- }
159
- }
160
-
161
- async getComments(_postId: string): Promise<SocialComment[]> {
162
- // Ayrshare comments not yet implemented
163
- return [];
164
- }
165
-
166
- async replyToComment(_postId: string, _commentId: string | null, _text: string): Promise<{ ok: boolean; error?: string }> {
167
- return { ok: false, error: "Ayrshare comment replies not yet implemented" };
168
- }
169
- }