cactus-react-native 0.2.5 → 0.2.7

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 (43) hide show
  1. package/README.md +48 -0
  2. package/ios/cactus.xcframework/ios-arm64_x86_64-simulator/cactus.framework/cactus +0 -0
  3. package/ios/cactus.xcframework/tvos-arm64_x86_64-simulator/cactus.framework/cactus +0 -0
  4. package/lib/commonjs/agent.js +70 -0
  5. package/lib/commonjs/agent.js.map +1 -0
  6. package/lib/commonjs/chat.js.map +1 -1
  7. package/lib/commonjs/index.js +17 -16
  8. package/lib/commonjs/index.js.map +1 -1
  9. package/lib/commonjs/lm.js +36 -15
  10. package/lib/commonjs/lm.js.map +1 -1
  11. package/lib/commonjs/telemetry.js +0 -1
  12. package/lib/commonjs/telemetry.js.map +1 -1
  13. package/lib/commonjs/vlm.js +0 -1
  14. package/lib/commonjs/vlm.js.map +1 -1
  15. package/lib/module/agent.js +65 -0
  16. package/lib/module/agent.js.map +1 -0
  17. package/lib/module/chat.js.map +1 -1
  18. package/lib/module/index.js +4 -17
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/lm.js +36 -15
  21. package/lib/module/lm.js.map +1 -1
  22. package/lib/module/telemetry.js +0 -1
  23. package/lib/module/telemetry.js.map +1 -1
  24. package/lib/module/vlm.js +0 -1
  25. package/lib/module/vlm.js.map +1 -1
  26. package/lib/typescript/agent.d.ts +30 -0
  27. package/lib/typescript/agent.d.ts.map +1 -0
  28. package/lib/typescript/chat.d.ts +2 -0
  29. package/lib/typescript/chat.d.ts.map +1 -1
  30. package/lib/typescript/index.d.ts +2 -7
  31. package/lib/typescript/index.d.ts.map +1 -1
  32. package/lib/typescript/lm.d.ts +5 -1
  33. package/lib/typescript/lm.d.ts.map +1 -1
  34. package/lib/typescript/telemetry.d.ts.map +1 -1
  35. package/lib/typescript/vlm.d.ts.map +1 -1
  36. package/package.json +1 -1
  37. package/src/agent.ts +109 -0
  38. package/src/chat.ts +3 -1
  39. package/src/index.ts +10 -16
  40. package/src/lm.ts +41 -15
  41. package/src/telemetry.ts +0 -1
  42. package/src/tools.ts +1 -1
  43. package/src/vlm.ts +0 -1
@@ -8,9 +8,13 @@ interface CactusLMReturn {
8
8
  export declare class CactusLM {
9
9
  protected context: LlamaContext;
10
10
  protected conversationHistoryManager: ConversationHistoryManager;
11
+ private initParams;
11
12
  private static _initCache;
12
13
  private static getCacheKey;
13
- protected constructor(context: LlamaContext);
14
+ protected constructor(context: LlamaContext, initParams: ContextParams);
15
+ private static isContextNotFoundError;
16
+ private reinit;
17
+ private run;
14
18
  static init(params: ContextParams, onProgress?: (progress: number) => void, cactusToken?: string, retryOptions?: {
15
19
  maxRetries?: number;
16
20
  delayMs?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"lm.d.ts","sourceRoot":"","sources":["../../src/lm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAE,MAAM,SAAS,CAAA;AAGjD,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,0BAA0B,EAC1B,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACtB,MAAM,SAAS,CAAA;AAIhB,OAAO,EAAE,0BAA0B,EAAE,MAAM,QAAQ,CAAA;AAEnD,UAAU,cAAc;IACtB,EAAE,EAAE,QAAQ,GAAG,IAAI,CAAA;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAED,qBAAa,QAAQ;IACnB,SAAS,CAAC,OAAO,EAAE,YAAY,CAAA;IAC/B,SAAS,CAAC,0BAA0B,EAAE,0BAA0B,CAAA;IAIhE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAmD;IAE5E,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,SAAS,aAAa,OAAO,EAAE,YAAY;WAK9B,IAAI,CACf,MAAM,EAAE,aAAa,EACrB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACvC,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACvD,OAAO,CAAC,cAAc,CAAC;IA8E1B,UAAU,GACR,UAAU,0BAA0B,EAAE,EACtC,SAAQ,gBAAqB,EAC7B,WAAW,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,KAC7B,OAAO,CAAC,sBAAsB,CAAC,CAqBjC;IAEK,SAAS,CACb,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,eAAe,EACxB,IAAI,GAAE,MAAgB,GACrB,OAAO,CAAC,qBAAqB,CAAC;cAoCjB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,qBAAqB,CAAC;cAI7F,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAOpF,MAAM,QAAa,OAAO,CAAC,IAAI,CAAC,CAE/B;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAItC"}
1
+ {"version":3,"file":"lm.d.ts","sourceRoot":"","sources":["../../src/lm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAE,MAAM,SAAS,CAAA;AAGjD,OAAO,KAAK,EACV,aAAa,EACb,gBAAgB,EAChB,0BAA0B,EAC1B,sBAAsB,EACtB,eAAe,EACf,qBAAqB,EACtB,MAAM,SAAS,CAAA;AAIhB,OAAO,EAAE,0BAA0B,EAAE,MAAM,QAAQ,CAAA;AAEnD,UAAU,cAAc;IACtB,EAAE,EAAE,QAAQ,GAAG,IAAI,CAAA;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAED,qBAAa,QAAQ;IACnB,SAAS,CAAC,OAAO,EAAE,YAAY,CAAA;IAC/B,SAAS,CAAC,0BAA0B,EAAE,0BAA0B,CAAA;IAChE,OAAO,CAAC,UAAU,CAAe;IACjC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAmD;IAE5E,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,SAAS,aAAa,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa;IAMtE,OAAO,CAAC,MAAM,CAAC,sBAAsB;YAKvB,MAAM;YAMN,GAAG;WAUJ,IAAI,CACf,MAAM,EAAE,aAAa,EACrB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACvC,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACvD,OAAO,CAAC,cAAc,CAAC;IA4E1B,UAAU,GACR,UAAU,0BAA0B,EAAE,EACtC,SAAQ,gBAAqB,EAC7B,WAAW,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,KAC7B,OAAO,CAAC,sBAAsB,CAAC,CAuBjC;IAEK,SAAS,CACb,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,eAAe,EACxB,IAAI,GAAE,MAAgB,GACrB,OAAO,CAAC,qBAAqB,CAAC;cAoCjB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,qBAAqB,CAAC;cAI7F,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAOpF,MAAM,QAAa,OAAO,CAAC,IAAI,CAAC,CAE/B;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAUxB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAItC"}
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/telemetry.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAmBD,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA0B;IACjD,OAAO,CAAC,MAAM,CAA4B;IAE1C,OAAO;IAOP,OAAO,CAAC,MAAM,CAAC,WAAW;IAQ1B,MAAM,CAAC,QAAQ,IAAI,IAAI;IASvB,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAM1C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAOhH,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAO1D,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,aAAa;YAuBP,UAAU;CAYzB"}
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/telemetry.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAmBD,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA0B;IACjD,OAAO,CAAC,MAAM,CAA4B;IAE1C,OAAO;IAOP,OAAO,CAAC,MAAM,CAAC,WAAW;IAQ1B,MAAM,CAAC,QAAQ,IAAI,IAAI;IASvB,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAM1C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAOhH,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAO1D,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,aAAa;YAuBP,UAAU;CAYzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"vlm.d.ts","sourceRoot":"","sources":["../../src/vlm.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC5B,MAAM,SAAS,CAAA;AAIhB,OAAO,EAAE,0BAA0B,EAAE,MAAM,QAAQ,CAAA;AAEnD,UAAU,eAAe;IACvB,GAAG,EAAE,SAAS,GAAG,IAAI,CAAA;IACrB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAED,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG;IAC7C,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GAAG;IACnE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAc;IAC7B,SAAS,CAAC,0BAA0B,EAAE,0BAA0B,CAAA;IAGhE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAoD;IAE7E,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO;WAKM,IAAI,CACf,MAAM,EAAE,gBAAgB,EACxB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACvC,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACvD,OAAO,CAAC,eAAe,CAAC;IA8ErB,UAAU,CACd,QAAQ,EAAE,0BAA0B,EAAE,EACtC,MAAM,GAAE,mBAAwB,EAChC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,GAC7B,OAAO,CAAC,sBAAsB,CAAC;IAuClC,OAAO,CAAC,sBAAsB,CAyC7B;YAEa,uBAAuB;IA+C/B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAGtC"}
1
+ {"version":3,"file":"vlm.d.ts","sourceRoot":"","sources":["../../src/vlm.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC5B,MAAM,SAAS,CAAA;AAIhB,OAAO,EAAE,0BAA0B,EAAE,MAAM,QAAQ,CAAA;AAEnD,UAAU,eAAe;IACvB,GAAG,EAAE,SAAS,GAAG,IAAI,CAAA;IACrB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAED,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG;IAC7C,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GAAG;IACnE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAc;IAC7B,SAAS,CAAC,0BAA0B,EAAE,0BAA0B,CAAA;IAEhE,OAAO,CAAC,MAAM,CAAC,UAAU,CAAoD;IAE7E,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO;WAKM,IAAI,CACf,MAAM,EAAE,gBAAgB,EACxB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACvC,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACvD,OAAO,CAAC,eAAe,CAAC;IA8ErB,UAAU,CACd,QAAQ,EAAE,0BAA0B,EAAE,EACtC,MAAM,GAAE,mBAAwB,EAChC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,GAC7B,OAAO,CAAC,sBAAsB,CAAC;IAuClC,OAAO,CAAC,sBAAsB,CAyC7B;YAEa,uBAAuB;IA+C/B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAGtC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cactus-react-native",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Run AI models locally on mobile devices",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
package/src/agent.ts ADDED
@@ -0,0 +1,109 @@
1
+ import { CactusLM } from './lm'
2
+
3
+ import type {
4
+ ContextParams,
5
+ CompletionParams,
6
+ CactusOAICompatibleMessage,
7
+ NativeCompletionResult,
8
+ TokenData,
9
+ } from './index'
10
+
11
+ import { Tools } from './tools'
12
+
13
+ interface Parameter {
14
+ type: string
15
+ description: string
16
+ required?: boolean
17
+ }
18
+
19
+ interface CactusAgentReturn {
20
+ agent: CactusAgent | null
21
+ error: Error | null
22
+ lm: CactusAgent | null
23
+ }
24
+
25
+ export interface AgentCompletionParams extends CompletionParams {
26
+ tools?: Tools
27
+ }
28
+
29
+ export class CactusAgent extends CactusLM {
30
+ private tools!: Tools
31
+
32
+ static async init(
33
+ params: ContextParams,
34
+ onProgress?: (progress: number) => void,
35
+ cactusToken?: string,
36
+ retryOptions?: { maxRetries?: number; delayMs?: number },
37
+ ): Promise<CactusAgentReturn> {
38
+ const result = await CactusLM.init(params, onProgress, cactusToken, retryOptions)
39
+
40
+ if (result.error || !result.lm) {
41
+ return { agent: null, error: result.error, lm: null }
42
+ }
43
+
44
+ const agent = Object.setPrototypeOf(result.lm, CactusAgent.prototype) as CactusAgent
45
+ agent.tools = new Tools()
46
+ return { agent, error: null, lm: agent }
47
+ }
48
+
49
+ addTool(
50
+ func: Function,
51
+ description: string,
52
+ parameters: { [key: string]: Parameter }
53
+ ): Function {
54
+ return this.tools.add(func, description, parameters)
55
+ }
56
+
57
+ getTools(): Tools {
58
+ return this.tools
59
+ }
60
+
61
+ async completionWithTools(
62
+ messages: CactusOAICompatibleMessage[],
63
+ params: AgentCompletionParams = {},
64
+ callback?: (data: TokenData) => void,
65
+ recursionCount: number = 0,
66
+ recursionLimit: number = 3
67
+ ): Promise<NativeCompletionResult> {
68
+ const tools = params.tools || this.tools
69
+
70
+ if (!messages?.length) {
71
+ return this.completion([], params, callback)
72
+ }
73
+ if (!tools || tools.getSchemas().length === 0) {
74
+ return this.completion(messages, params, callback)
75
+ }
76
+ if (recursionCount >= recursionLimit) {
77
+ return this.completion(messages, {
78
+ ...params,
79
+ jinja: true,
80
+ tools: tools.getSchemas()
81
+ }, callback)
82
+ }
83
+
84
+ const { newMessages, requiresReset } =
85
+ this.conversationHistoryManager.processNewMessages(messages)
86
+
87
+ if (requiresReset) {
88
+ this.context?.rewind()
89
+ this.conversationHistoryManager.reset()
90
+ }
91
+
92
+ const result = await this.context.completionWithTools({
93
+ ...params,
94
+ messages: newMessages.length > 0 ? newMessages : messages,
95
+ tools: tools
96
+ }, callback, recursionCount, recursionLimit)
97
+
98
+ this.conversationHistoryManager.update(
99
+ newMessages.length > 0 ? newMessages : messages,
100
+ {
101
+ role: 'assistant',
102
+ content: result.content,
103
+ tool_calls: result.tool_calls
104
+ }
105
+ )
106
+
107
+ return result
108
+ }
109
+ }
package/src/chat.ts CHANGED
@@ -6,7 +6,9 @@ export type CactusMessagePart = {
6
6
 
7
7
  export type CactusOAICompatibleMessage = {
8
8
  role: string
9
- content?: string | CactusMessagePart[] | any
9
+ content?: string | CactusMessagePart[] | any
10
+ tool_calls?: any[]
11
+ tool_call_id?: string
10
12
  }
11
13
 
12
14
  export function formatChat(
package/src/index.ts CHANGED
@@ -27,7 +27,6 @@ import type { CactusMessagePart, CactusOAICompatibleMessage } from './chat'
27
27
  import { formatChat } from './chat'
28
28
  import { Tools, parseAndExecuteTool } from './tools'
29
29
  import { Telemetry, type TelemetryParams } from './telemetry'
30
-
31
30
  export type {
32
31
  NativeContextParams,
33
32
  NativeLlamaContext,
@@ -45,9 +44,11 @@ export type {
45
44
  JinjaFormattedChatResult,
46
45
  NativeAudioDecodeResult,
47
46
  }
48
-
49
- export {Tools }
50
47
  export * from './remote'
48
+ export {
49
+ Tools,
50
+ parseAndExecuteTool
51
+ } from './tools'
51
52
 
52
53
  const EVENT_ON_INIT_CONTEXT_PROGRESS = '@Cactus_onInitContextProgress'
53
54
  const EVENT_ON_TOKEN = '@Cactus_onToken'
@@ -72,7 +73,6 @@ if (EventEmitter) {
72
73
  logListeners.forEach((listener) => listener(evt.level, evt.text))
73
74
  },
74
75
  )
75
- // Trigger unset to use default log callback
76
76
  Cactus?.toggleNativeLog?.(false)?.catch?.(() => {})
77
77
  }
78
78
 
@@ -181,18 +181,12 @@ export class LlamaContext {
181
181
  this.model = model
182
182
  }
183
183
 
184
- /**
185
- * Load cached prompt & completion state from a file.
186
- */
187
184
  async loadSession(filepath: string): Promise<NativeSessionLoadResult> {
188
185
  let path = filepath
189
186
  if (path.startsWith('file://')) path = path.slice(7)
190
187
  return Cactus.loadSession(this.id, path)
191
188
  }
192
189
 
193
- /**
194
- * Save current cached prompt & completion state to a file.
195
- */
196
190
  async saveSession(
197
191
  filepath: string,
198
192
  options?: { tokenSize: number },
@@ -242,10 +236,10 @@ export class LlamaContext {
242
236
  recursionCount: number = 0,
243
237
  recursionLimit: number = 3
244
238
  ): Promise<NativeCompletionResult> {
245
- if (!params.messages) { // tool calling only works with messages
239
+ if (!params.messages) {
246
240
  return this.completion(params, callback);
247
241
  }
248
- if (!params.tools) { // no tools => default completion
242
+ if (!params.tools) {
249
243
  return this.completion(params, callback);
250
244
  }
251
245
  if (recursionCount >= recursionLimit) {
@@ -256,7 +250,7 @@ export class LlamaContext {
256
250
  }, callback);
257
251
  }
258
252
 
259
- const messages = [...params.messages]; // avoid mutating the original messages
253
+ const messages = [...params.messages];
260
254
 
261
255
  const result = await this.completion({
262
256
  ...params,
@@ -307,7 +301,7 @@ export class LlamaContext {
307
301
  emit_partial_completion: !!callback,
308
302
  }
309
303
  if (params.messages) {
310
- // messages always win
304
+
311
305
  const formattedResult = await this.getFormattedChat(
312
306
  params.messages,
313
307
  params.chat_template || params.chatTemplate,
@@ -502,7 +496,6 @@ export async function loadLlamaModelInfo(model: string): Promise<Object> {
502
496
  }
503
497
 
504
498
  const poolTypeMap = {
505
- // -1 is unspecified as undefined
506
499
  none: 0,
507
500
  mean: 1,
508
501
  cls: 2,
@@ -665,4 +658,5 @@ export const getDeviceInfo = async (contextId: number): Promise<NativeDeviceInfo
665
658
 
666
659
  export { CactusLM } from './lm';
667
660
  export { CactusVLM } from './vlm';
668
- export { CactusTTS } from './tts';
661
+ export { CactusTTS } from './tts';
662
+ export { CactusAgent } from './agent';
package/src/lm.ts CHANGED
@@ -22,20 +22,40 @@ interface CactusLMReturn {
22
22
  export class CactusLM {
23
23
  protected context: LlamaContext
24
24
  protected conversationHistoryManager: ConversationHistoryManager
25
-
26
- // the initPromise enables a "async singleton" initialization pattern which
27
- // protects against a race condition in the event of multiple init attempts
25
+ private initParams: ContextParams
28
26
  private static _initCache: Map<string, Promise<CactusLMReturn>> = new Map();
29
27
 
30
28
  private static getCacheKey(params: ContextParams, cactusToken?: string, retryOptions?: { maxRetries?: number; delayMs?: number }): string {
31
29
  return JSON.stringify({ params, cactusToken, retryOptions });
32
30
  }
33
31
 
34
- protected constructor(context: LlamaContext) {
32
+ protected constructor(context: LlamaContext, initParams: ContextParams) {
35
33
  this.context = context
34
+ this.initParams = initParams
36
35
  this.conversationHistoryManager = new ConversationHistoryManager()
37
36
  }
38
37
 
38
+ private static isContextNotFoundError(e: unknown): boolean {
39
+ const message = String((e as any)?.message ?? e ?? '')
40
+ return /context not found/i.test(message)
41
+ }
42
+
43
+ private async reinit(): Promise<void> {
44
+ const newContext = await initLlama(this.initParams)
45
+ this.context = newContext
46
+ this.conversationHistoryManager.reset()
47
+ }
48
+
49
+ private async run<T>(op: () => Promise<T>): Promise<T> {
50
+ try {
51
+ return await op()
52
+ } catch (e) {
53
+ if (!CactusLM.isContextNotFoundError(e)) throw e
54
+ await this.reinit()
55
+ return await op()
56
+ }
57
+ }
58
+
39
59
  static async init(
40
60
  params: ContextParams,
41
61
  onProgress?: (progress: number) => void,
@@ -49,7 +69,6 @@ export class CactusLM {
49
69
 
50
70
  const key = CactusLM.getCacheKey(params, cactusToken, retryOptions);
51
71
  if (CactusLM._initCache.has(key)) {
52
- // concurrent initialization calls with the same params all get the same cached Promise
53
72
  return CactusLM._initCache.get(key)!;
54
73
  }
55
74
 
@@ -82,7 +101,7 @@ export class CactusLM {
82
101
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
83
102
  try {
84
103
  const context = await initLlama(config, onProgress);
85
- return { lm: new CactusLM(context), error: null };
104
+ return { lm: new CactusLM(context, config), error: null };
86
105
  } catch (e) {
87
106
  lastError = e as Error;
88
107
  const isLastConfig = configs.indexOf(config) === configs.length - 1;
@@ -113,9 +132,8 @@ export class CactusLM {
113
132
  CactusLM._initCache.set(key, initPromise);
114
133
 
115
134
  const result = await initPromise;
116
- if (result.error) {
117
- CactusLM._initCache.delete(key); // Reset on failure to allow retries
118
- }
135
+ // Cache only while in-flight; never cache resolved instances
136
+ CactusLM._initCache.delete(key);
119
137
  return result;
120
138
  }
121
139
 
@@ -128,7 +146,7 @@ export class CactusLM {
128
146
  this.conversationHistoryManager.processNewMessages(messages);
129
147
 
130
148
  if (requiresReset) {
131
- this.context?.rewind();
149
+ await this.run(() => this.context.rewind())
132
150
  this.conversationHistoryManager.reset();
133
151
  }
134
152
 
@@ -136,7 +154,9 @@ export class CactusLM {
136
154
  console.warn('No messages to complete!');
137
155
  }
138
156
 
139
- const result = await this.context.completion({ messages: newMessages, ...params }, callback);
157
+ const result = await this.run(() =>
158
+ this.context.completion({ messages: newMessages, ...params }, callback),
159
+ )
140
160
 
141
161
  this.conversationHistoryManager.update(newMessages, {
142
162
  role: 'assistant',
@@ -187,7 +207,7 @@ export class CactusLM {
187
207
  }
188
208
 
189
209
  protected async _handleLocalEmbedding(text: string, params?: EmbeddingParams): Promise<NativeEmbeddingResult> {
190
- return this.context.embedding(text, params);
210
+ return this.run(() => this.context.embedding(text, params))
191
211
  }
192
212
 
193
213
  protected async _handleRemoteEmbedding(text: string): Promise<NativeEmbeddingResult> {
@@ -198,15 +218,21 @@ export class CactusLM {
198
218
  }
199
219
 
200
220
  rewind = async (): Promise<void> => {
201
- return this.context?.rewind()
221
+ return this.run(() => this.context.rewind())
202
222
  }
203
223
 
204
224
  async release(): Promise<void> {
205
- return this.context.release()
225
+ try {
226
+ return await this.context.release()
227
+ } catch (e) {
228
+ // Treat missing context as already released
229
+ if (CactusLM.isContextNotFoundError(e)) return
230
+ throw e
231
+ }
206
232
  }
207
233
 
208
234
  async stopCompletion(): Promise<void> {
209
- return await this.context.stopCompletion()
235
+ return await this.run(() => this.context.stopCompletion())
210
236
  }
211
237
 
212
238
  }
package/src/telemetry.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Platform } from 'react-native'
2
- // Import package.json to get version
3
2
  const packageJson = require('../package.json');
4
3
  import { PROJECT_ID } from './projectId';
5
4
 
package/src/tools.ts CHANGED
@@ -3,7 +3,7 @@ import type { NativeCompletionResult } from "./NativeCactus";
3
3
  interface Parameter {
4
4
  type: string,
5
5
  description: string,
6
- required?: boolean // parameter is optional if not specified
6
+ required?: boolean
7
7
  }
8
8
 
9
9
  interface Tool {
package/src/vlm.ts CHANGED
@@ -31,7 +31,6 @@ export class CactusVLM {
31
31
  private context: LlamaContext
32
32
  protected conversationHistoryManager: ConversationHistoryManager
33
33
 
34
- // see CactusLM for detailed docs
35
34
  private static _initCache: Map<string, Promise<CactusVLMReturn>> = new Map();
36
35
 
37
36
  private static getCacheKey(params: VLMContextParams, cactusToken?: string, retryOptions?: { maxRetries?: number; delayMs?: number }): string {