@forge/llm 0.1.0 → 0.2.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -67,6 +67,11 @@ The response is a `ChatResponse` object:
67
67
 
68
68
  ```json
69
69
  {
70
+ "usage": {
71
+ "input_tokens": 150,
72
+ "output_tokens": 50,
73
+ "total_tokens": 200
74
+ },
70
75
  "choices": [
71
76
  {
72
77
  "finish_reason": "tool_use",
@@ -75,7 +80,7 @@ The response is a `ChatResponse` object:
75
80
  "content": [
76
81
  {
77
82
  "type": "text",
78
- "text": "I'll help you check the weather in Melbourne using the WeatherTool."
83
+ "text": "I'll help you check the weather in Melbourne using the WeatherTool."
79
84
  }
80
85
  ],
81
86
  "tool_calls": [
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
3
4
  const fetch_wrapper_1 = require("../fetch-wrapper");
4
5
  const llm_api_1 = require("../llm-api");
5
6
  const errors_1 = require("../errors");
6
7
  const test_helpers_1 = require("./test-helpers");
8
+ const responseMapper = tslib_1.__importStar(require("../response-mapper"));
7
9
  function setupEnvironment(response) {
8
10
  const mockedFetch = jest.fn().mockResolvedValue(response || new Response(null, { status: 200 }));
9
11
  global.__forge_fetch__ = jest.fn((_ctx, path, options) => mockedFetch(path, options));
@@ -84,21 +86,11 @@ describe('llm api', () => {
84
86
  setupEnvironment(apiResponse);
85
87
  const llmAPI = new llm_api_1.LlmApiImpl((0, fetch_wrapper_1.getFetchWrapper)());
86
88
  const prompt = (0, test_helpers_1.constructPrompt)();
89
+ const mapResponseSpy = jest.spyOn(responseMapper, 'mapForgeLLMResponse');
87
90
  const response = await llmAPI.chat(prompt);
88
- expect(response.choices[0]).toEqual({
89
- finish_reason: 'tool_calls',
90
- message: {
91
- content: [
92
- {
93
- type: 'text',
94
- text: "It's 20 degrees celsius"
95
- }
96
- ],
97
- role: 'assistant',
98
- tool_calls: undefined
99
- },
100
- index: 19
101
- });
91
+ expect(mapResponseSpy).toHaveBeenCalledWith(apiResponse);
92
+ expect(response.choices).toEqual(llmResponse.choices);
93
+ expect(response.usage).toEqual(llmResponse.usage);
102
94
  });
103
95
  it('should throw an error for a non-200 response', async () => {
104
96
  const apiResponse = new Response(JSON.stringify({}), {
@@ -7,7 +7,7 @@ describe('response mapper', () => {
7
7
  const llmResponseBody = { choices: [] };
8
8
  const apiResponse = (0, test_helpers_1.makeApiResponse)({ json: () => Promise.resolve(llmResponseBody) });
9
9
  const mappedResponse = await (0, response_mapper_1.mapForgeLLMResponse)(apiResponse);
10
- expect(mappedResponse).toEqual({ choices: [] });
10
+ expect(mappedResponse).toEqual({ choices: [], usage: undefined });
11
11
  });
12
12
  it('should map the Forge LLM response', async () => {
13
13
  const llmResponseBody = {
@@ -40,6 +40,34 @@ describe('response mapper', () => {
40
40
  };
41
41
  const apiResponse = (0, test_helpers_1.makeApiResponse)({ json: () => Promise.resolve(llmResponseBody) });
42
42
  const mappedResponse = await (0, response_mapper_1.mapForgeLLMResponse)(apiResponse);
43
- expect(mappedResponse).toEqual({ choices: llmResponseBody.choices });
43
+ expect(mappedResponse).toEqual({ choices: llmResponseBody.choices, usage: undefined });
44
+ });
45
+ it('should map the Forge LLM response with usage attribute', async () => {
46
+ const llmResponseBody = {
47
+ choices: [
48
+ {
49
+ finish_reason: 'stop',
50
+ message: {
51
+ role: 'assistant',
52
+ content: [{ type: 'text', text: 'Hello!' }]
53
+ }
54
+ }
55
+ ],
56
+ usage: {
57
+ input_token: 10,
58
+ output_token: 20,
59
+ total_token: 30
60
+ }
61
+ };
62
+ const apiResponse = (0, test_helpers_1.makeApiResponse)({ json: () => Promise.resolve(llmResponseBody) });
63
+ const mappedResponse = await (0, response_mapper_1.mapForgeLLMResponse)(apiResponse);
64
+ expect(mappedResponse).toEqual({
65
+ choices: llmResponseBody.choices,
66
+ usage: {
67
+ input_token: 10,
68
+ output_token: 20,
69
+ total_token: 30
70
+ }
71
+ });
44
72
  });
45
73
  });
@@ -15,5 +15,6 @@ export declare const constructLlmResponse: (overrides?: Partial<Choice>) => {
15
15
  }[];
16
16
  };
17
17
  }[];
18
+ usage: {};
18
19
  };
19
20
  //# sourceMappingURL=test-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../../src/__test__/test-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,eAAO,MAAM,eAAe,sBAAqB,MAU/C,CAAC;AAEH,eAAO,MAAM,eAAe,cAAe,QAAQ,WAAW,CAAC,KAAG,WAWjE,CAAC;AAEF,eAAO,MAAM,oBAAoB,eAAe,QAAQ,MAAM,CAAC;;;;;;;;;;;;CAiB7D,CAAC"}
1
+ {"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../../src/__test__/test-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,eAAO,MAAM,eAAe,sBAAqB,MAU/C,CAAC;AAEH,eAAO,MAAM,eAAe,cAAe,QAAQ,WAAW,CAAC,KAAG,WAWjE,CAAC;AAEF,eAAO,MAAM,oBAAoB,eAAe,QAAQ,MAAM,CAAC;;;;;;;;;;;;;CAkB7D,CAAC"}
@@ -42,6 +42,7 @@ const constructLlmResponse = (overrides = {}) => ({
42
42
  index: 19,
43
43
  ...overrides
44
44
  }
45
- ]
45
+ ],
46
+ usage: {}
46
47
  });
47
48
  exports.constructLlmResponse = constructLlmResponse;
@@ -25,14 +25,6 @@ export declare type ToolChoice = 'auto' | 'none' | 'required' | {
25
25
  name: string;
26
26
  };
27
27
  };
28
- export interface LlmResponseTool {
29
- id: string;
30
- type: 'function';
31
- function: {
32
- name: string;
33
- arguments: Record<string, unknown>;
34
- };
35
- }
36
28
  export interface SystemMessage {
37
29
  content: Content;
38
30
  role: 'system';
@@ -63,12 +55,18 @@ export interface ToolCall {
63
55
  }
64
56
  export interface LlmResponse {
65
57
  choices: Choice[];
58
+ usage?: Usage;
66
59
  }
67
60
  export interface Choice {
68
61
  finish_reason: string;
69
62
  index?: number;
70
63
  message: AssistantMessage;
71
64
  }
65
+ export interface Usage {
66
+ input_token?: number;
67
+ output_token?: number;
68
+ total_token?: number;
69
+ }
72
70
  export declare type Content = string | ContentPart[];
73
71
  export declare type ContentPart = TextPart;
74
72
  export interface TextPart {
@@ -1 +1 @@
1
- {"version":3,"file":"llm-api.d.ts","sourceRoot":"","sources":["../../src/interfaces/llm-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE/C,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B;AAED,oBAAY,OAAO,GAAG,aAAa,GAAG,WAAW,GAAG,gBAAgB,GAAG,WAAW,CAAC;AAEnF,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACrC,CAAC;CACH;AAED,oBAAY,UAAU,GAClB,MAAM,GACN,MAAM,GACN,UAAU,GACV;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH,CAAC;AAEN,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,MAAM;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED,oBAAY,OAAO,GAAG,MAAM,GAAG,WAAW,EAAE,CAAC;AAE7C,oBAAY,WAAW,GAAG,QAAQ,CAAC;AAEnC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd"}
1
+ {"version":3,"file":"llm-api.d.ts","sourceRoot":"","sources":["../../src/interfaces/llm-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE/C,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B;AAED,oBAAY,OAAO,GAAG,aAAa,GAAG,WAAW,GAAG,gBAAgB,GAAG,WAAW,CAAC;AAEnF,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACrC,CAAC;CACH;AAED,oBAAY,UAAU,GAClB,MAAM,GACN,MAAM,GACN,UAAU,GACV;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH,CAAC;AAEN,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,MAAM,WAAW,MAAM;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAED,MAAM,WAAW,KAAK;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,oBAAY,OAAO,GAAG,MAAM,GAAG,WAAW,EAAE,CAAC;AAE7C,oBAAY,WAAW,GAAG,QAAQ,CAAC;AAEnC,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd"}
@@ -1,10 +1,10 @@
1
1
  import { ForgeLlmError, PromptValidationError } from '../errors';
2
- import { LlmRequest, LlmResponse, Message, Tool, ToolCall } from './llm-api';
2
+ import { LlmRequest, LlmResponse, Message, Tool, ToolCall, Usage } from './llm-api';
3
3
  export declare type Prompt = LlmRequest & {
4
4
  model: string;
5
5
  };
6
6
  export declare type ChatResponse = LlmResponse;
7
7
  export declare type ToolSchema = Tool;
8
- export type { Message, ToolCall };
8
+ export type { Message, ToolCall, Usage };
9
9
  export { ForgeLlmError, PromptValidationError };
10
10
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/interfaces/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE7E,oBAAY,MAAM,GAAG,UAAU,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,oBAAY,YAAY,GAAG,WAAW,CAAC;AAEvC,oBAAY,UAAU,GAAG,IAAI,CAAC;AAE9B,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/interfaces/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAEpF,oBAAY,MAAM,GAAG,UAAU,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,oBAAY,YAAY,GAAG,WAAW,CAAC;AAEvC,oBAAY,UAAU,GAAG,IAAI,CAAC;AAE9B,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"response-mapper.d.ts","sourceRoot":"","sources":["../src/response-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,eAAO,MAAM,mBAAmB,aAAoB,WAAW,KAAG,QAAQ,YAAY,CAIrF,CAAC"}
1
+ {"version":3,"file":"response-mapper.d.ts","sourceRoot":"","sources":["../src/response-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,eAAO,MAAM,mBAAmB,aAAoB,WAAW,KAAG,QAAQ,YAAY,CAGrF,CAAC"}
@@ -2,8 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mapForgeLLMResponse = void 0;
4
4
  const mapForgeLLMResponse = async (response) => {
5
- const jsonBody = await response.json();
6
- const choices = jsonBody.choices ?? [];
7
- return { choices };
5
+ const chatResponse = await response.json();
6
+ return chatResponse;
8
7
  };
9
8
  exports.mapForgeLLMResponse = mapForgeLLMResponse;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge/llm",
3
- "version": "0.1.0",
3
+ "version": "0.2.0-next.1",
4
4
  "description": "Forge LLM SDK",
5
5
  "main": "out/index.js",
6
6
  "types": "out/index.d.ts",
@@ -10,7 +10,7 @@
10
10
  "author": "Atlassian",
11
11
  "license": "SEE LICENSE IN LICENSE.txt",
12
12
  "dependencies": {
13
- "@forge/api": "^6.2.0"
13
+ "@forge/api": "^6.2.1-next.0"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/node": "20.19.1",