@ztimson/momentum 1.2.2 → 1.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/dist/ai.d.ts CHANGED
@@ -1,14 +1,24 @@
1
- import { PathEventEmitter } from './core';
1
+ import { AssetController } from './asset-controller';
2
+ import { Meta, PathEventEmitter } from './core';
2
3
  import { Momentum } from './momentum';
3
- export type AiInfo = {
4
- /** Service provider: Anthropic, OpenAI, Ollama */
5
- readonly host: string;
6
- /** Assistant LLM version */
7
- readonly model: string;
8
- /** Available tools */
9
- readonly tools: {
10
- [name: string]: string;
11
- };
4
+ /** AI personality */
5
+ export type AiAgent = Meta & {
6
+ /** Agent name */
7
+ _id: string;
8
+ /** Default model when none is specified */
9
+ default?: boolean;
10
+ /** LLM model */
11
+ model: string;
12
+ /** System prompt & instructions */
13
+ system: string;
14
+ /** LLM temperature */
15
+ temperature: number;
16
+ /** Optional skills whitelist */
17
+ skills?: string[] | null;
18
+ /** Optional skills whitelist */
19
+ tools?: string[] | null;
20
+ /** Optional MCP whitelist */
21
+ mcp?: string[] | null;
12
22
  };
13
23
  export type AiMessage = {
14
24
  /** Message originator */
@@ -33,26 +43,84 @@ export type AiMessage = {
33
43
  /** Timestamp */
34
44
  timestamp?: number;
35
45
  };
46
+ /** Provider connection info */
47
+ export type AiModel = {
48
+ /** Model name */
49
+ name: string;
50
+ /** LLM Protocol */
51
+ proto: 'anthropic' | 'openai' | 'ollama';
52
+ /** Host address (omit for Claud & ChatGPT models) */
53
+ host?: string;
54
+ /** Authentication token */
55
+ token?: string;
56
+ };
57
+ /**
58
+ * Configuration options defining the interaction settings for an AI agent session.
59
+ * Includes identification of the target agent, optional context information parsed separately from user messages, file attachments to be processed with the message, and a streaming callback handler that manages progress events such as response chunks, completion status, and tool invocation updates.
60
+ */
61
+ export type AiOptions = {
62
+ /** Which AI agent are you speaking to */
63
+ agent?: string;
64
+ /** Additional context information kept separate from user messages */
65
+ context?: any;
66
+ /** Files that will be parsed with message */
67
+ files?: File[];
68
+ };
69
+ /** Skills the LLM can call learn on demand */
70
+ export type AiSkill = Meta & {
71
+ /** Human-readable name */
72
+ _id: string;
73
+ /** Skill description for AI */
74
+ description: string;
75
+ /** Skill instructions */
76
+ content: string;
77
+ };
78
+ /**
79
+ * Streams LLM responses
80
+ * text - Text chunk, combine them to get the full response
81
+ * done - When LLM is done you receive a single chunk with the done flag
82
+ * tool - Tool that was called
83
+ */
84
+ export type LLMStream = (chunk: {
85
+ text?: string;
86
+ done?: boolean;
87
+ tool?: string;
88
+ }) => any;
89
+ /** Model Context Protocol Server */
90
+ export type McpServer = {
91
+ /** Human-readable server name */
92
+ name: string;
93
+ /** URL connection info */
94
+ host: string;
95
+ /** Authentication token */
96
+ token?: string;
97
+ };
98
+ /** Manage and render templates */
99
+ export declare class Agents extends AssetController<AiAgent> {
100
+ protected momentum: Momentum;
101
+ constructor(momentum: Momentum);
102
+ }
103
+ /** Manage and render templates */
104
+ export declare class Skills extends AssetController<AiSkill> {
105
+ protected momentum: Momentum;
106
+ constructor(momentum: Momentum);
107
+ }
36
108
  /** AI integrations */
37
109
  export declare class Ai extends PathEventEmitter {
38
110
  protected momentum: Momentum;
111
+ agents: Agents;
112
+ skills: Skills;
39
113
  constructor(momentum: Momentum);
40
114
  /** Cancel current AI requests */
41
115
  abort(): Promise<void>;
42
116
  /**
43
117
  * Ask the AI assistant a question
44
118
  * @param {string} question Users question
45
- * @param {context: string, stream: Function} options context - Any hidden context information. stream - Receive response in chunks
119
+ * @param {AiOptions & {stream: Function}} options context - Any hidden context information. stream - Receive response in chunks
46
120
  * @return {Promise<string>} AI's response
47
121
  */
48
- ask(question: string, options?: {
49
- context?: any;
50
- files?: File[];
51
- stream?: (chunk: {
52
- text?: string;
53
- done?: boolean;
54
- tool?: string;
55
- }) => any;
122
+ ask(question: string, options?: AiOptions & {
123
+ stream?: LLMStream;
56
124
  }): Promise<string>;
57
125
  /**
58
126
  * Clear AI assistant memory & context
@@ -68,6 +136,8 @@ export declare class Ai extends PathEventEmitter {
68
136
  * Get model info
69
137
  * @return {AiInfo>} Model Info
70
138
  */
71
- info(): Promise<AiInfo>;
139
+ tools(): Promise<{
140
+ [name: string]: string;
141
+ }>;
72
142
  }
73
143
  //# sourceMappingURL=ai.d.ts.map
package/dist/ai.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../src/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAM,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEpC,MAAM,MAAM,MAAM,GAAG;IACpB,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sBAAsB;IACtB,QAAQ,CAAC,KAAK,EAAE;QAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAC,CAAA;CACxC,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACvB,yBAAyB;IACzB,IAAI,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;IACtC,sBAAsB;IACtB,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IACtB,gBAAgB;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG;IACH,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,IAAI,EAAE,GAAG,CAAC;IACV,kBAAkB;IAClB,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC;IAC5B,iBAAiB;IACjB,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,gBAAgB;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAA;AAED,sBAAsB;AACtB,qBAAa,EAAG,SAAQ,gBAAgB;IAC3B,SAAS,CAAC,QAAQ,EAAE,QAAQ;gBAAlB,QAAQ,EAAE,QAAQ;IAIxC,iCAAiC;IACjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB;;;;;OAKG;IACG,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE;QAAC,OAAO,CAAC,EAAE,GAAG,CAAC;QAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,OAAO,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAC,KAAK,GAAG,CAAA;KAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA2BpK;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAO/B;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;CAGvB"}
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../src/ai.ts"],"names":[],"mappings":"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"}
package/dist/call.d.ts CHANGED
@@ -2,7 +2,7 @@ import { Message, PathEventEmitter } from './core';
2
2
  import { Momentum } from './momentum';
3
3
  export type AiReceptionist = {
4
4
  ai: {
5
- tools?: [];
5
+ agent: string;
6
6
  } & InteractiveCall;
7
7
  };
8
8
  export type ForwardCall = {
@@ -1 +1 @@
1
- {"version":3,"file":"call.d.ts","sourceRoot":"","sources":["../src/call.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,gBAAgB,EAAM,MAAM,QAAQ,CAAC;AACtD,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEpC,MAAM,MAAM,cAAc,GAAG;IAAC,EAAE,EAAE;QAAC,KAAK,CAAC,EAAE,EAAE,CAAA;KAAC,GAAG,eAAe,CAAA;CAAC,CAAA;AACjE,MAAM,MAAM,WAAW,GAAG;IAAC,OAAO,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,GAAG;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC,CAAC;AACzG,MAAM,MAAM,UAAU,GAAG;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC;AAC1C,MAAM,MAAM,UAAU,GAAG;IAAC,MAAM,EAAE;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC,CAAC;AACrF,MAAM,MAAM,MAAM,GAAG;IAAC,MAAM,EAAE,IAAI,CAAA;CAAC,CAAC;AACpC,MAAM,MAAM,eAAe,GAAG;IAC7B,sBAAsB;IACtB,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;IACrE,8CAA8C;IAC9C,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,eAAe,CAAC;CAC1G,CAAC;AAEF,6BAA6B;AAC7B,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG;IAC/C,0FAA0F;IAC1F,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC;IAC/B,qCAAqC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB,CAAA;AAED,oBAAoB;AACpB,qBAAa,IAAK,SAAQ,gBAAgB;IAC7B,SAAS,CAAC,QAAQ,EAAE,QAAQ;gBAAlB,QAAQ,EAAE,QAAQ;IAIxC;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC;IAKxC;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC;CAGnD"}
1
+ {"version":3,"file":"call.d.ts","sourceRoot":"","sources":["../src/call.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAE,gBAAgB,EAAM,MAAM,QAAQ,CAAC;AACtD,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEpC,MAAM,MAAM,cAAc,GAAG;IAAC,EAAE,EAAE;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,GAAG,eAAe,CAAA;CAAC,CAAC;AACrE,MAAM,MAAM,WAAW,GAAG;IAAC,OAAO,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,GAAG;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC,CAAC;AACzG,MAAM,MAAM,UAAU,GAAG;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC;AAC1C,MAAM,MAAM,UAAU,GAAG;IAAC,MAAM,EAAE;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,CAAA;CAAC,CAAC;AACrF,MAAM,MAAM,MAAM,GAAG;IAAC,MAAM,EAAE,IAAI,CAAA;CAAC,CAAC;AACpC,MAAM,MAAM,eAAe,GAAG;IAC7B,sBAAsB;IACtB,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;IACrE,8CAA8C;IAC9C,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,eAAe,CAAC;CAC1G,CAAC;AAEF,6BAA6B;AAC7B,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG;IAC/C,0FAA0F;IAC1F,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC;IAC/B,qCAAqC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB,CAAA;AAED,oBAAoB;AACpB,qBAAa,IAAK,SAAQ,gBAAgB;IAC7B,SAAS,CAAC,QAAQ,EAAE,QAAQ;gBAAlB,QAAQ,EAAE,QAAQ;IAIxC;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC;IAKxC;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC;CAGnD"}
package/dist/index.js CHANGED
@@ -667,9 +667,46 @@
667
667
  function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(), tz = "local") {
668
668
  if (typeof date === "number" || typeof date === "string") date = new Date(date);
669
669
  if (isNaN(date.getTime())) throw new Error("Invalid date input");
670
- const numericTz = typeof tz === "number";
671
- const localTz = tz === "local" || !numericTz && tz.toLowerCase?.() === "local";
672
- const tzName = localTz ? Intl.DateTimeFormat().resolvedOptions().timeZone : numericTz ? "UTC" : tz;
670
+ const TIMEZONE_MAP = [
671
+ { name: "IDLW", iana: "Etc/GMT+12", offset: -720 },
672
+ { name: "SST", iana: "Pacific/Pago_Pago", offset: -660 },
673
+ { name: "HST", iana: "Pacific/Honolulu", offset: -600 },
674
+ { name: "AKST", iana: "America/Anchorage", offset: -540 },
675
+ { name: "PST", iana: "America/Los_Angeles", offset: -480 },
676
+ { name: "MST", iana: "America/Denver", offset: -420 },
677
+ { name: "CST", iana: "America/Chicago", offset: -360 },
678
+ { name: "EST", iana: "America/New_York", offset: -300 },
679
+ { name: "AST", iana: "America/Halifax", offset: -240 },
680
+ { name: "BRT", iana: "America/Sao_Paulo", offset: -180 },
681
+ { name: "MAT", iana: "Atlantic/South_Georgia", offset: -120 },
682
+ { name: "AZOT", iana: "Atlantic/Azores", offset: -60 },
683
+ { name: "UTC", iana: "UTC", offset: 0 },
684
+ { name: "CET", iana: "Europe/Paris", offset: 60 },
685
+ { name: "EET", iana: "Europe/Athens", offset: 120 },
686
+ { name: "MSK", iana: "Europe/Moscow", offset: 180 },
687
+ { name: "GST", iana: "Asia/Dubai", offset: 240 },
688
+ { name: "PKT", iana: "Asia/Karachi", offset: 300 },
689
+ { name: "IST", iana: "Asia/Kolkata", offset: 330 },
690
+ { name: "BST", iana: "Asia/Dhaka", offset: 360 },
691
+ { name: "ICT", iana: "Asia/Bangkok", offset: 420 },
692
+ { name: "CST", iana: "Asia/Shanghai", offset: 480 },
693
+ { name: "JST", iana: "Asia/Tokyo", offset: 540 },
694
+ { name: "AEST", iana: "Australia/Sydney", offset: 600 },
695
+ { name: "SBT", iana: "Pacific/Guadalcanal", offset: 660 },
696
+ { name: "TOT", iana: "Pacific/Tongatapu", offset: 780 },
697
+ { name: "LINT", iana: "Pacific/Kiritimati", offset: 840 }
698
+ ];
699
+ let numericTz = typeof tz === "number";
700
+ const localTz = tz === "local" || !numericTz && tz.toString().toLowerCase?.() === "local";
701
+ let tzName = localTz ? Intl.DateTimeFormat().resolvedOptions().timeZone : numericTz ? "UTC" : tz;
702
+ let offsetMinutes = 0;
703
+ if (numericTz) {
704
+ offsetMinutes = Math.abs(tz) < 24 ? tz * 60 : tz;
705
+ const closest = TIMEZONE_MAP.reduce(
706
+ (prev, curr) => Math.abs(curr.offset - offsetMinutes) < Math.abs(prev.offset - offsetMinutes) ? curr : prev
707
+ );
708
+ tzName = closest.iana;
709
+ }
673
710
  if (!numericTz && tzName !== "UTC") {
674
711
  try {
675
712
  new Intl.DateTimeFormat("en-US", { timeZone: tzName }).format();
@@ -696,7 +733,7 @@
696
733
  partsMap[p.type] = p.value;
697
734
  });
698
735
  const monthValue = parseInt(partsMap.month) - 1;
699
- const dayOfWeekValue = (/* @__PURE__ */ new Date(`${partsMap.year}-${partsMap.month}-${partsMap.day}`)).getDay();
736
+ const dayOfWeekValue = new Date(Date.UTC(parseInt(partsMap.year), parseInt(partsMap.month) - 1, parseInt(partsMap.day))).getUTCDay();
700
737
  const hourValue = parseInt(partsMap.hour);
701
738
  get = (fn2) => {
702
739
  switch (fn2) {
@@ -719,8 +756,7 @@
719
756
  }
720
757
  };
721
758
  } else {
722
- const offset = numericTz ? tz : 0;
723
- zonedDate = new Date(date.getTime() + offset * 60 * 60 * 1e3);
759
+ zonedDate = new Date(date.getTime() + offsetMinutes * 60 * 1e3);
724
760
  get = (fn2) => zonedDate[`getUTC${fn2}`]();
725
761
  }
726
762
  function numSuffix2(n) {
@@ -730,10 +766,9 @@
730
766
  }
731
767
  function getTZOffset() {
732
768
  if (numericTz) {
733
- const total = tz * 60;
734
- const hours = Math.floor(Math.abs(total) / 60);
735
- const mins = Math.abs(total) % 60;
736
- return `${tz >= 0 ? "+" : "-"}${String(hours).padStart(2, "0")}:${String(mins).padStart(2, "0")}`;
769
+ const hours = Math.floor(Math.abs(offsetMinutes) / 60);
770
+ const mins = Math.abs(offsetMinutes) % 60;
771
+ return `${offsetMinutes >= 0 ? "+" : "-"}${String(hours).padStart(2, "0")}:${String(mins).padStart(2, "0")}`;
737
772
  }
738
773
  try {
739
774
  const offset = new Intl.DateTimeFormat("en-US", { timeZone: tzName, timeZoneName: "longOffset", hour: "2-digit", minute: "2-digit" }).formatToParts(date).find((p) => p.type === "timeZoneName")?.value.match(/([+-]\d{2}:\d{2})/)?.[1];
@@ -743,7 +778,6 @@
743
778
  return "+00:00";
744
779
  }
745
780
  function getTZAbbr() {
746
- if (numericTz && tz === 0) return "UTC";
747
781
  try {
748
782
  return new Intl.DateTimeFormat("en-US", { timeZone: tzName, timeZoneName: "short" }).formatToParts(date).find((p) => p.type === "timeZoneName")?.value || "";
749
783
  } catch {
@@ -1814,12 +1848,32 @@
1814
1848
  return this.momentum.api.request({ ...opts, url: `api/actions/run/${path}` });
1815
1849
  }
1816
1850
  }
1851
+ class Agents extends AssetController {
1852
+ constructor(momentum) {
1853
+ super(momentum, { module: "agents", path: "ai/agents", key: "_id" });
1854
+ this.momentum = momentum;
1855
+ }
1856
+ momentum;
1857
+ }
1858
+ class Skills extends AssetController {
1859
+ constructor(momentum) {
1860
+ super(momentum, { module: "skills", path: "ai/skills", key: "_id" });
1861
+ this.momentum = momentum;
1862
+ }
1863
+ momentum;
1864
+ }
1817
1865
  class Ai extends PathEventEmitter {
1818
1866
  constructor(momentum) {
1819
1867
  super("ai");
1820
1868
  this.momentum = momentum;
1869
+ this.agents = new Agents(momentum);
1870
+ this.skills = new Skills(momentum);
1871
+ this.relayEvents(this.agents);
1872
+ this.relayEvents(this.skills);
1821
1873
  }
1822
1874
  momentum;
1875
+ agents;
1876
+ skills;
1823
1877
  /** Cancel current AI requests */
1824
1878
  abort() {
1825
1879
  return this.momentum.api.request({ url: "/api/ai/abort", method: "POST" });
@@ -1827,7 +1881,7 @@
1827
1881
  /**
1828
1882
  * Ask the AI assistant a question
1829
1883
  * @param {string} question Users question
1830
- * @param {context: string, stream: Function} options context - Any hidden context information. stream - Receive response in chunks
1884
+ * @param {AiOptions & {stream: Function}} options context - Any hidden context information. stream - Receive response in chunks
1831
1885
  * @return {Promise<string>} AI's response
1832
1886
  */
1833
1887
  async ask(question, options = {}) {
@@ -1837,7 +1891,7 @@
1837
1891
  reader.onload = () => res([f.name, reader.result]);
1838
1892
  reader.readAsDataURL(f);
1839
1893
  })))).reduce((acc, f) => ({ ...acc, [f[0]]: f[1] }), {});
1840
- const q = { question: question.trim(), context: options.context, files };
1894
+ const q = { agent: options?.agent, question: question.trim(), context: options.context, files };
1841
1895
  if (options.stream && this.momentum.socket?.connected) {
1842
1896
  let unsub = () => {
1843
1897
  };
@@ -1878,8 +1932,8 @@
1878
1932
  * Get model info
1879
1933
  * @return {AiInfo>} Model Info
1880
1934
  */
1881
- info() {
1882
- return this.momentum.api.request({ url: "api/ai/info" });
1935
+ tools() {
1936
+ return this.momentum.api.request({ url: "api/ai/tools" });
1883
1937
  }
1884
1938
  }
1885
1939
  let dialogCount = 0;
@@ -4196,7 +4250,7 @@ ${log}`;
4196
4250
  }
4197
4251
  momentum;
4198
4252
  }
4199
- const version = "1.2.2";
4253
+ const version = "1.3.0";
4200
4254
  class WebRtc extends PathEventEmitter {
4201
4255
  constructor(momentum) {
4202
4256
  super("webrtc");
@@ -4483,6 +4537,7 @@ ${log}`;
4483
4537
  }
4484
4538
  exports2.ActionType = ActionType;
4485
4539
  exports2.Actions = Actions;
4540
+ exports2.Agents = Agents;
4486
4541
  exports2.Ai = Ai;
4487
4542
  exports2.Analytics = Analytics;
4488
4543
  exports2.Api = Api;
@@ -4511,6 +4566,7 @@ ${log}`;
4511
4566
  exports2.Routes = Routes;
4512
4567
  exports2.Schemas = Schemas;
4513
4568
  exports2.Settings = Settings;
4569
+ exports2.Skills = Skills;
4514
4570
  exports2.Sms = Sms;
4515
4571
  exports2.Socket = Socket;
4516
4572
  exports2.Static = Static;
package/dist/index.mjs CHANGED
@@ -663,9 +663,46 @@ function dayOfYear(date) {
663
663
  function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(), tz = "local") {
664
664
  if (typeof date === "number" || typeof date === "string") date = new Date(date);
665
665
  if (isNaN(date.getTime())) throw new Error("Invalid date input");
666
- const numericTz = typeof tz === "number";
667
- const localTz = tz === "local" || !numericTz && tz.toLowerCase?.() === "local";
668
- const tzName = localTz ? Intl.DateTimeFormat().resolvedOptions().timeZone : numericTz ? "UTC" : tz;
666
+ const TIMEZONE_MAP = [
667
+ { name: "IDLW", iana: "Etc/GMT+12", offset: -720 },
668
+ { name: "SST", iana: "Pacific/Pago_Pago", offset: -660 },
669
+ { name: "HST", iana: "Pacific/Honolulu", offset: -600 },
670
+ { name: "AKST", iana: "America/Anchorage", offset: -540 },
671
+ { name: "PST", iana: "America/Los_Angeles", offset: -480 },
672
+ { name: "MST", iana: "America/Denver", offset: -420 },
673
+ { name: "CST", iana: "America/Chicago", offset: -360 },
674
+ { name: "EST", iana: "America/New_York", offset: -300 },
675
+ { name: "AST", iana: "America/Halifax", offset: -240 },
676
+ { name: "BRT", iana: "America/Sao_Paulo", offset: -180 },
677
+ { name: "MAT", iana: "Atlantic/South_Georgia", offset: -120 },
678
+ { name: "AZOT", iana: "Atlantic/Azores", offset: -60 },
679
+ { name: "UTC", iana: "UTC", offset: 0 },
680
+ { name: "CET", iana: "Europe/Paris", offset: 60 },
681
+ { name: "EET", iana: "Europe/Athens", offset: 120 },
682
+ { name: "MSK", iana: "Europe/Moscow", offset: 180 },
683
+ { name: "GST", iana: "Asia/Dubai", offset: 240 },
684
+ { name: "PKT", iana: "Asia/Karachi", offset: 300 },
685
+ { name: "IST", iana: "Asia/Kolkata", offset: 330 },
686
+ { name: "BST", iana: "Asia/Dhaka", offset: 360 },
687
+ { name: "ICT", iana: "Asia/Bangkok", offset: 420 },
688
+ { name: "CST", iana: "Asia/Shanghai", offset: 480 },
689
+ { name: "JST", iana: "Asia/Tokyo", offset: 540 },
690
+ { name: "AEST", iana: "Australia/Sydney", offset: 600 },
691
+ { name: "SBT", iana: "Pacific/Guadalcanal", offset: 660 },
692
+ { name: "TOT", iana: "Pacific/Tongatapu", offset: 780 },
693
+ { name: "LINT", iana: "Pacific/Kiritimati", offset: 840 }
694
+ ];
695
+ let numericTz = typeof tz === "number";
696
+ const localTz = tz === "local" || !numericTz && tz.toString().toLowerCase?.() === "local";
697
+ let tzName = localTz ? Intl.DateTimeFormat().resolvedOptions().timeZone : numericTz ? "UTC" : tz;
698
+ let offsetMinutes = 0;
699
+ if (numericTz) {
700
+ offsetMinutes = Math.abs(tz) < 24 ? tz * 60 : tz;
701
+ const closest = TIMEZONE_MAP.reduce(
702
+ (prev, curr) => Math.abs(curr.offset - offsetMinutes) < Math.abs(prev.offset - offsetMinutes) ? curr : prev
703
+ );
704
+ tzName = closest.iana;
705
+ }
669
706
  if (!numericTz && tzName !== "UTC") {
670
707
  try {
671
708
  new Intl.DateTimeFormat("en-US", { timeZone: tzName }).format();
@@ -692,7 +729,7 @@ function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(
692
729
  partsMap[p.type] = p.value;
693
730
  });
694
731
  const monthValue = parseInt(partsMap.month) - 1;
695
- const dayOfWeekValue = (/* @__PURE__ */ new Date(`${partsMap.year}-${partsMap.month}-${partsMap.day}`)).getDay();
732
+ const dayOfWeekValue = new Date(Date.UTC(parseInt(partsMap.year), parseInt(partsMap.month) - 1, parseInt(partsMap.day))).getUTCDay();
696
733
  const hourValue = parseInt(partsMap.hour);
697
734
  get = (fn2) => {
698
735
  switch (fn2) {
@@ -715,8 +752,7 @@ function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(
715
752
  }
716
753
  };
717
754
  } else {
718
- const offset = numericTz ? tz : 0;
719
- zonedDate = new Date(date.getTime() + offset * 60 * 60 * 1e3);
755
+ zonedDate = new Date(date.getTime() + offsetMinutes * 60 * 1e3);
720
756
  get = (fn2) => zonedDate[`getUTC${fn2}`]();
721
757
  }
722
758
  function numSuffix2(n) {
@@ -726,10 +762,9 @@ function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(
726
762
  }
727
763
  function getTZOffset() {
728
764
  if (numericTz) {
729
- const total = tz * 60;
730
- const hours = Math.floor(Math.abs(total) / 60);
731
- const mins = Math.abs(total) % 60;
732
- return `${tz >= 0 ? "+" : "-"}${String(hours).padStart(2, "0")}:${String(mins).padStart(2, "0")}`;
765
+ const hours = Math.floor(Math.abs(offsetMinutes) / 60);
766
+ const mins = Math.abs(offsetMinutes) % 60;
767
+ return `${offsetMinutes >= 0 ? "+" : "-"}${String(hours).padStart(2, "0")}:${String(mins).padStart(2, "0")}`;
733
768
  }
734
769
  try {
735
770
  const offset = new Intl.DateTimeFormat("en-US", { timeZone: tzName, timeZoneName: "longOffset", hour: "2-digit", minute: "2-digit" }).formatToParts(date).find((p) => p.type === "timeZoneName")?.value.match(/([+-]\d{2}:\d{2})/)?.[1];
@@ -739,7 +774,6 @@ function formatDate(format = "YYYY-MM-DD H:mm", date = /* @__PURE__ */ new Date(
739
774
  return "+00:00";
740
775
  }
741
776
  function getTZAbbr() {
742
- if (numericTz && tz === 0) return "UTC";
743
777
  try {
744
778
  return new Intl.DateTimeFormat("en-US", { timeZone: tzName, timeZoneName: "short" }).formatToParts(date).find((p) => p.type === "timeZoneName")?.value || "";
745
779
  } catch {
@@ -1810,12 +1844,32 @@ class Actions extends AssetController {
1810
1844
  return this.momentum.api.request({ ...opts, url: `api/actions/run/${path}` });
1811
1845
  }
1812
1846
  }
1847
+ class Agents extends AssetController {
1848
+ constructor(momentum) {
1849
+ super(momentum, { module: "agents", path: "ai/agents", key: "_id" });
1850
+ this.momentum = momentum;
1851
+ }
1852
+ momentum;
1853
+ }
1854
+ class Skills extends AssetController {
1855
+ constructor(momentum) {
1856
+ super(momentum, { module: "skills", path: "ai/skills", key: "_id" });
1857
+ this.momentum = momentum;
1858
+ }
1859
+ momentum;
1860
+ }
1813
1861
  class Ai extends PathEventEmitter {
1814
1862
  constructor(momentum) {
1815
1863
  super("ai");
1816
1864
  this.momentum = momentum;
1865
+ this.agents = new Agents(momentum);
1866
+ this.skills = new Skills(momentum);
1867
+ this.relayEvents(this.agents);
1868
+ this.relayEvents(this.skills);
1817
1869
  }
1818
1870
  momentum;
1871
+ agents;
1872
+ skills;
1819
1873
  /** Cancel current AI requests */
1820
1874
  abort() {
1821
1875
  return this.momentum.api.request({ url: "/api/ai/abort", method: "POST" });
@@ -1823,7 +1877,7 @@ class Ai extends PathEventEmitter {
1823
1877
  /**
1824
1878
  * Ask the AI assistant a question
1825
1879
  * @param {string} question Users question
1826
- * @param {context: string, stream: Function} options context - Any hidden context information. stream - Receive response in chunks
1880
+ * @param {AiOptions & {stream: Function}} options context - Any hidden context information. stream - Receive response in chunks
1827
1881
  * @return {Promise<string>} AI's response
1828
1882
  */
1829
1883
  async ask(question, options = {}) {
@@ -1833,7 +1887,7 @@ class Ai extends PathEventEmitter {
1833
1887
  reader.onload = () => res([f.name, reader.result]);
1834
1888
  reader.readAsDataURL(f);
1835
1889
  })))).reduce((acc, f) => ({ ...acc, [f[0]]: f[1] }), {});
1836
- const q = { question: question.trim(), context: options.context, files };
1890
+ const q = { agent: options?.agent, question: question.trim(), context: options.context, files };
1837
1891
  if (options.stream && this.momentum.socket?.connected) {
1838
1892
  let unsub = () => {
1839
1893
  };
@@ -1874,8 +1928,8 @@ class Ai extends PathEventEmitter {
1874
1928
  * Get model info
1875
1929
  * @return {AiInfo>} Model Info
1876
1930
  */
1877
- info() {
1878
- return this.momentum.api.request({ url: "api/ai/info" });
1931
+ tools() {
1932
+ return this.momentum.api.request({ url: "api/ai/tools" });
1879
1933
  }
1880
1934
  }
1881
1935
  let dialogCount = 0;
@@ -4192,7 +4246,7 @@ class Static extends Storage {
4192
4246
  }
4193
4247
  momentum;
4194
4248
  }
4195
- const version = "1.2.2";
4249
+ const version = "1.3.0";
4196
4250
  class WebRtc extends PathEventEmitter {
4197
4251
  constructor(momentum) {
4198
4252
  super("webrtc");
@@ -4480,6 +4534,7 @@ class Momentum extends PathEventEmitter {
4480
4534
  export {
4481
4535
  ActionType,
4482
4536
  Actions,
4537
+ Agents,
4483
4538
  Ai,
4484
4539
  Analytics,
4485
4540
  Api,
@@ -4508,6 +4563,7 @@ export {
4508
4563
  Routes,
4509
4564
  Schemas,
4510
4565
  Settings,
4566
+ Skills,
4511
4567
  Sms,
4512
4568
  Socket,
4513
4569
  Static,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ztimson/momentum",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "Client library for momentum",
5
5
  "keywords": [
6
6
  "Momentum"
@@ -33,7 +33,7 @@
33
33
  "postbuild": "npm run build:docs && node -e \"const fs=require('fs');fs.cpSync('dist/index.mjs','../server/public/momentum.mjs');fs.cpSync('dist/index.js','../server/public/momentum.js');fs.cpSync('dist/momentum.worker.mjs','../server/public/momentum.worker.mjs')\""
34
34
  },
35
35
  "dependencies": {
36
- "@ztimson/utils": "0.29.1"
36
+ "@ztimson/utils": "^0.29.4"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^22.5.4",