@inferencesh/sdk 0.2.1 → 0.4.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/client.d.ts +3 -3
- package/dist/client.js +10 -4
- package/dist/integration.test.d.ts +9 -0
- package/dist/integration.test.js +98 -0
- package/dist/types.d.ts +29 -26
- package/dist/types.js +5 -7
- package/package.json +6 -4
package/dist/client.d.ts
CHANGED
|
@@ -77,10 +77,10 @@ export declare class Inference {
|
|
|
77
77
|
* @param options - Run options for waiting, updates, and reconnection
|
|
78
78
|
* @returns The completed task result
|
|
79
79
|
*
|
|
80
|
-
* App reference format: `namespace/name@shortid`
|
|
80
|
+
* App reference format: `namespace/name@shortid` or `namespace/name@shortid:function`
|
|
81
81
|
*
|
|
82
|
-
* The short ID ensures your code always runs the same version
|
|
83
|
-
*
|
|
82
|
+
* The short ID ensures your code always runs the same version.
|
|
83
|
+
* You can optionally specify a function name to run a specific entry point.
|
|
84
84
|
*
|
|
85
85
|
* @example
|
|
86
86
|
* ```typescript
|
package/dist/client.js
CHANGED
|
@@ -82,7 +82,13 @@ class Inference {
|
|
|
82
82
|
}
|
|
83
83
|
const apiResponse = data;
|
|
84
84
|
if (!apiResponse?.success) {
|
|
85
|
-
|
|
85
|
+
// Build a helpful error message
|
|
86
|
+
let errorMessage = apiResponse?.error?.message;
|
|
87
|
+
if (!errorMessage) {
|
|
88
|
+
// No error message provided - show the response for debugging
|
|
89
|
+
errorMessage = `Request failed (success=false). Response: ${responseText.slice(0, 500)}`;
|
|
90
|
+
}
|
|
91
|
+
throw new errors_1.InferenceError(response.status, errorMessage, responseText);
|
|
86
92
|
}
|
|
87
93
|
return apiResponse.data;
|
|
88
94
|
}
|
|
@@ -150,10 +156,10 @@ class Inference {
|
|
|
150
156
|
* @param options - Run options for waiting, updates, and reconnection
|
|
151
157
|
* @returns The completed task result
|
|
152
158
|
*
|
|
153
|
-
* App reference format: `namespace/name@shortid`
|
|
159
|
+
* App reference format: `namespace/name@shortid` or `namespace/name@shortid:function`
|
|
154
160
|
*
|
|
155
|
-
* The short ID ensures your code always runs the same version
|
|
156
|
-
*
|
|
161
|
+
* The short ID ensures your code always runs the same version.
|
|
162
|
+
* You can optionally specify a function name to run a specific entry point.
|
|
157
163
|
*
|
|
158
164
|
* @example
|
|
159
165
|
* ```typescript
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Integration tests for @inferencesh/sdk
|
|
4
|
+
*
|
|
5
|
+
* These tests hit the real API and require INFERENCE_API_KEY to be set.
|
|
6
|
+
* Run with: npm run test:integration
|
|
7
|
+
*
|
|
8
|
+
* @jest-environment node
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
const client_1 = require("./client");
|
|
12
|
+
const types_1 = require("./types");
|
|
13
|
+
// Skip all tests if no API key is set
|
|
14
|
+
const API_KEY = process.env.INFERENCE_API_KEY;
|
|
15
|
+
const BASE_URL = process.env.INFERENCE_BASE_URL || 'https://api.inference.sh';
|
|
16
|
+
// Use a pinned app version that's known to work
|
|
17
|
+
const TEST_APP = 'infsh/text-templating@53bk0yzk';
|
|
18
|
+
const describeIfApiKey = API_KEY ? describe : describe.skip;
|
|
19
|
+
describeIfApiKey('Integration Tests', () => {
|
|
20
|
+
let client;
|
|
21
|
+
beforeAll(() => {
|
|
22
|
+
client = new client_1.Inference({
|
|
23
|
+
apiKey: API_KEY,
|
|
24
|
+
baseUrl: BASE_URL,
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('Basic Run', () => {
|
|
28
|
+
it('should run a simple task and wait for completion', async () => {
|
|
29
|
+
const result = await client.run({
|
|
30
|
+
app: TEST_APP,
|
|
31
|
+
input: { template: 'Hello {1}!', strings: ['Jest'] },
|
|
32
|
+
});
|
|
33
|
+
expect(result).toBeDefined();
|
|
34
|
+
expect(result.id).toBeDefined();
|
|
35
|
+
expect(result.status).toBe(types_1.TaskStatusCompleted);
|
|
36
|
+
expect(result.output).toBeDefined();
|
|
37
|
+
}, 60000); // 60 second timeout for API call
|
|
38
|
+
});
|
|
39
|
+
describe('Run with Updates', () => {
|
|
40
|
+
it('should receive status updates during task execution', async () => {
|
|
41
|
+
const updates = [];
|
|
42
|
+
const result = await client.run({
|
|
43
|
+
app: TEST_APP,
|
|
44
|
+
input: { template: 'Testing {1}', strings: ['SDK'] },
|
|
45
|
+
}, {
|
|
46
|
+
onUpdate: (update) => {
|
|
47
|
+
updates.push(update.status);
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
expect(result.status).toBe(types_1.TaskStatusCompleted);
|
|
51
|
+
expect(updates.length).toBeGreaterThan(0);
|
|
52
|
+
}, 60000);
|
|
53
|
+
});
|
|
54
|
+
describe('Fire and Forget', () => {
|
|
55
|
+
it('should submit a task without waiting for completion', async () => {
|
|
56
|
+
const result = await client.run({
|
|
57
|
+
app: TEST_APP,
|
|
58
|
+
input: { template: '{1}', strings: ['Fire and forget'] },
|
|
59
|
+
}, { wait: false });
|
|
60
|
+
expect(result).toBeDefined();
|
|
61
|
+
expect(result.id).toBeDefined();
|
|
62
|
+
// Status should NOT be completed yet (task was just submitted)
|
|
63
|
+
expect(result.status).not.toBe(types_1.TaskStatusCompleted);
|
|
64
|
+
expect(result.status).not.toBe(types_1.TaskStatusFailed);
|
|
65
|
+
}, 30000);
|
|
66
|
+
});
|
|
67
|
+
describe('Factory Function', () => {
|
|
68
|
+
it('should work with lowercase inference() factory', async () => {
|
|
69
|
+
const factoryClient = (0, client_1.inference)({
|
|
70
|
+
apiKey: API_KEY,
|
|
71
|
+
baseUrl: BASE_URL,
|
|
72
|
+
});
|
|
73
|
+
const result = await factoryClient.run({
|
|
74
|
+
app: TEST_APP,
|
|
75
|
+
input: { template: '{1}', strings: ['Factory test'] },
|
|
76
|
+
}, { wait: false });
|
|
77
|
+
expect(result).toBeDefined();
|
|
78
|
+
expect(result.id).toBeDefined();
|
|
79
|
+
}, 30000);
|
|
80
|
+
});
|
|
81
|
+
describe('Error Handling', () => {
|
|
82
|
+
it('should throw an error for non-existent app', async () => {
|
|
83
|
+
await expect(client.run({
|
|
84
|
+
app: 'non-existent/app-that-does-not-exist@xyz123',
|
|
85
|
+
input: {},
|
|
86
|
+
}, { wait: false })).rejects.toThrow();
|
|
87
|
+
}, 30000);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
// Add a simple test that always runs to ensure Jest doesn't complain about no tests
|
|
91
|
+
describe('Integration Test Setup', () => {
|
|
92
|
+
it('should have API key check', () => {
|
|
93
|
+
if (!API_KEY) {
|
|
94
|
+
console.log('⚠️ Skipping integration tests - INFERENCE_API_KEY not set');
|
|
95
|
+
}
|
|
96
|
+
expect(true).toBe(true);
|
|
97
|
+
});
|
|
98
|
+
});
|
package/dist/types.d.ts
CHANGED
|
@@ -312,10 +312,6 @@ export interface ApiAppRunRequest {
|
|
|
312
312
|
*/
|
|
313
313
|
stream?: boolean;
|
|
314
314
|
}
|
|
315
|
-
/**
|
|
316
|
-
* ApiTaskRequest is an alias for ApiAppRunRequest (deprecated name)
|
|
317
|
-
*/
|
|
318
|
-
export type ApiTaskRequest = ApiAppRunRequest;
|
|
319
315
|
/**
|
|
320
316
|
* ApiAgentRunRequest is the request body for /agents/run endpoint.
|
|
321
317
|
* Supports both template agents and ad-hoc agents.
|
|
@@ -346,10 +342,6 @@ export interface ApiAgentRunRequest {
|
|
|
346
342
|
*/
|
|
347
343
|
stream?: boolean;
|
|
348
344
|
}
|
|
349
|
-
/**
|
|
350
|
-
* ApiAgentMessageRequest is an alias for ApiAgentRunRequest (deprecated name)
|
|
351
|
-
*/
|
|
352
|
-
export type ApiAgentMessageRequest = ApiAgentRunRequest;
|
|
353
345
|
export interface CreateAgentMessageRequest {
|
|
354
346
|
chat_id?: string;
|
|
355
347
|
agent_id?: string;
|
|
@@ -364,18 +356,10 @@ export interface CreateAgentMessageRequest {
|
|
|
364
356
|
*/
|
|
365
357
|
agent_config?: AgentRuntimeConfig;
|
|
366
358
|
}
|
|
367
|
-
export interface
|
|
359
|
+
export interface CreateAgentMessageResponse {
|
|
368
360
|
user_message?: ChatMessageDTO;
|
|
369
361
|
assistant_message?: ChatMessageDTO;
|
|
370
362
|
}
|
|
371
|
-
/**
|
|
372
|
-
* WidgetActionRequest represents a user's response to a widget
|
|
373
|
-
* @deprecated Use ToolResultRequest with action field instead
|
|
374
|
-
*/
|
|
375
|
-
export interface WidgetActionRequest {
|
|
376
|
-
action: WidgetAction;
|
|
377
|
-
form_data?: WidgetFormData;
|
|
378
|
-
}
|
|
379
363
|
/**
|
|
380
364
|
* ToolResultRequest represents a tool result submission
|
|
381
365
|
* For widget actions, clients should JSON-serialize { action, form_data } as the result string
|
|
@@ -662,6 +646,16 @@ export interface AppVariant {
|
|
|
662
646
|
};
|
|
663
647
|
python: string;
|
|
664
648
|
}
|
|
649
|
+
/**
|
|
650
|
+
* AppFunction represents a callable entry point within an app version.
|
|
651
|
+
* Each function has its own input/output schema while sharing the app's setup.
|
|
652
|
+
*/
|
|
653
|
+
export interface AppFunction {
|
|
654
|
+
name: string;
|
|
655
|
+
description?: string;
|
|
656
|
+
input_schema: any;
|
|
657
|
+
output_schema: any;
|
|
658
|
+
}
|
|
665
659
|
export interface AppVersion {
|
|
666
660
|
BaseModel: BaseModel;
|
|
667
661
|
/**
|
|
@@ -679,6 +673,15 @@ export interface AppVersion {
|
|
|
679
673
|
setup_schema: any;
|
|
680
674
|
input_schema: any;
|
|
681
675
|
output_schema: any;
|
|
676
|
+
/**
|
|
677
|
+
* Functions contains the callable entry points for this app version.
|
|
678
|
+
* Each function has its own input/output schema. If nil/empty, the app uses legacy single-function mode
|
|
679
|
+
* with InputSchema/OutputSchema at the version level.
|
|
680
|
+
*/
|
|
681
|
+
functions?: {
|
|
682
|
+
[key: string]: AppFunction;
|
|
683
|
+
};
|
|
684
|
+
default_function?: string;
|
|
682
685
|
variants: {
|
|
683
686
|
[key: string]: AppVariant;
|
|
684
687
|
};
|
|
@@ -713,6 +716,10 @@ export interface AppVersionDTO extends BaseModel {
|
|
|
713
716
|
setup_schema: any;
|
|
714
717
|
input_schema: any;
|
|
715
718
|
output_schema: any;
|
|
719
|
+
functions?: {
|
|
720
|
+
[key: string]: AppFunction;
|
|
721
|
+
};
|
|
722
|
+
default_function?: string;
|
|
716
723
|
variants: {
|
|
717
724
|
[key: string]: AppVariant;
|
|
718
725
|
};
|
|
@@ -757,9 +764,7 @@ export interface PermissionModelDTO {
|
|
|
757
764
|
export type ChatStatus = string;
|
|
758
765
|
export declare const ChatStatusBusy: ChatStatus;
|
|
759
766
|
export declare const ChatStatusIdle: ChatStatus;
|
|
760
|
-
|
|
761
|
-
* ChatStatusWaitingInput ChatStatus = "waiting_input"
|
|
762
|
-
*/
|
|
767
|
+
export declare const ChatStatusAwaitingInput: ChatStatus;
|
|
763
768
|
export declare const ChatStatusCompleted: ChatStatus;
|
|
764
769
|
export interface IntegrationContext {
|
|
765
770
|
integration_type?: IntegrationType;
|
|
@@ -771,6 +776,7 @@ export interface IntegrationContext {
|
|
|
771
776
|
export interface ChatData {
|
|
772
777
|
plan_steps: PlanStep[];
|
|
773
778
|
memory: StringEncodedMap;
|
|
779
|
+
always_allowed_tools: string[];
|
|
774
780
|
}
|
|
775
781
|
/**
|
|
776
782
|
* PlanStep represents a step in an agent's execution plan
|
|
@@ -1014,6 +1020,7 @@ export interface FlowNodeData {
|
|
|
1014
1020
|
app?: AppDTO;
|
|
1015
1021
|
app_id: string;
|
|
1016
1022
|
app_version_id: string;
|
|
1023
|
+
function?: string;
|
|
1017
1024
|
infra: Infra;
|
|
1018
1025
|
workers: string[];
|
|
1019
1026
|
setup?: any;
|
|
@@ -1396,6 +1403,7 @@ export interface TaskDTO extends BaseModel, PermissionModelDTO {
|
|
|
1396
1403
|
app_version_id: string;
|
|
1397
1404
|
app_version?: AppVersionDTO;
|
|
1398
1405
|
app_variant: string;
|
|
1406
|
+
function: string;
|
|
1399
1407
|
infra: Infra;
|
|
1400
1408
|
workers: string[];
|
|
1401
1409
|
flow_id?: string;
|
|
@@ -1744,6 +1752,7 @@ export interface User {
|
|
|
1744
1752
|
default_team_id: string;
|
|
1745
1753
|
role: Role;
|
|
1746
1754
|
email: string;
|
|
1755
|
+
email_verified: boolean;
|
|
1747
1756
|
name: string;
|
|
1748
1757
|
full_name: string;
|
|
1749
1758
|
avatar_url: string;
|
|
@@ -1867,9 +1876,3 @@ export interface Widget {
|
|
|
1867
1876
|
children?: WidgetNode[];
|
|
1868
1877
|
actions?: WidgetActionButton[];
|
|
1869
1878
|
}
|
|
1870
|
-
/**
|
|
1871
|
-
* WidgetFormData represents the form data collected from widget inputs
|
|
1872
|
-
*/
|
|
1873
|
-
export type WidgetFormData = {
|
|
1874
|
-
[key: string]: any;
|
|
1875
|
-
};
|
package/dist/types.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// Code generated by tygo. DO NOT EDIT.
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
5
|
-
exports.
|
|
6
|
-
exports.
|
|
7
|
-
exports.WidgetNodeTypeStatusBadge = exports.WidgetNodeTypeKeyValue = exports.WidgetNodeTypePlanList = exports.WidgetNodeTypeCol = exports.WidgetNodeTypeRow = exports.WidgetNodeTypeCheckbox = void 0;
|
|
4
|
+
exports.DeviceAuthStatusExpired = exports.DeviceAuthStatusApproved = exports.DeviceAuthStatusPending = exports.IntegrationTypeTelegram = exports.IntegrationTypeTeams = exports.IntegrationTypeDiscord = exports.IntegrationTypeSlack = exports.ChatMessageContentTypeTool = exports.ChatMessageContentTypeFile = exports.ChatMessageContentTypeImage = exports.ChatMessageContentTypeReasoning = exports.ChatMessageContentTypeText = exports.ChatMessageStatusCancelled = exports.ChatMessageStatusFailed = exports.ChatMessageStatusReady = exports.ChatMessageStatusPending = exports.ChatMessageRoleTool = exports.ChatMessageRoleAssistant = exports.ChatMessageRoleUser = exports.ChatMessageRoleSystem = exports.PlanStepStatusCancelled = exports.PlanStepStatusCompleted = exports.PlanStepStatusInProgress = exports.PlanStepStatusPending = exports.ChatStatusCompleted = exports.ChatStatusAwaitingInput = exports.ChatStatusIdle = exports.ChatStatusBusy = exports.VisibilityUnlisted = exports.VisibilityPublic = exports.VisibilityPrivate = exports.GPUTypeApple = exports.GPUTypeAMD = exports.GPUTypeNvidia = exports.GPUTypeIntel = exports.GPUTypeNone = exports.GPUTypeAny = exports.AppCategoryFlow = exports.AppCategoryOther = exports.AppCategory3D = exports.AppCategoryChat = exports.AppCategoryText = exports.AppCategoryAudio = exports.AppCategoryVideo = exports.AppCategoryImage = exports.ToolTypeInternal = exports.ToolTypeClient = exports.ToolTypeHook = exports.ToolTypeAgent = exports.ToolTypeApp = void 0;
|
|
5
|
+
exports.InfraPrivate = exports.TaskStatusCancelled = exports.TaskStatusFailed = exports.TaskStatusCompleted = exports.TaskStatusUploading = exports.TaskStatusRunning = exports.TaskStatusSettingUp = exports.TaskStatusServing = exports.TaskStatusPreparing = exports.TaskStatusScheduled = exports.TaskStatusQueued = exports.TaskStatusReceived = exports.TaskStatusUnknown = exports.InstanceStatusDeleted = exports.InstanceStatusActive = exports.InstanceStatusPending = exports.CloudShade = exports.CloudVultr = exports.CloudMassedCompute = exports.CloudDatacrunch = exports.CloudPaperspace = exports.CloudOblivus = exports.CloudJarvisLabs = exports.CloudLatitude = exports.CloudRunPod = exports.CloudTensorDock = exports.CloudLambdaLabs = exports.CloudAzure = exports.CloudAWS = exports.ContentUnrated = exports.ContentSelfHarm = exports.ContentDrugs = exports.ContentGore = exports.ContentViolenceGraphic = exports.ContentViolenceNonGraphic = exports.ContentSexualExplicit = exports.ContentSexualSuggestive = exports.ContentSafe = exports.ProjectTypeOther = exports.ProjectTypeFlow = exports.ProjectTypeApp = exports.ProjectTypeAgent = exports.EngineStatusStopped = exports.EngineStatusStopping = exports.EngineStatusPending = exports.EngineStatusRunning = exports.DeviceAuthStatusLoading = exports.DeviceAuthStatusInvalid = exports.DeviceAuthStatusValid = exports.DeviceAuthStatusDenied = void 0;
|
|
6
|
+
exports.WidgetNodeTypeInput = exports.WidgetNodeTypeButton = exports.WidgetNodeTypeBadge = exports.WidgetNodeTypeImage = exports.WidgetNodeTypeMarkdown = exports.WidgetNodeTypeText = exports.RoleSystem = exports.RoleAdmin = exports.RoleUser = exports.RoleGuest = exports.VideoRes4K = exports.VideoRes1440P = exports.VideoRes1080P = exports.VideoRes720P = exports.VideoRes480P = exports.MetaItemTypeRaw = exports.MetaItemTypeAudio = exports.MetaItemTypeVideo = exports.MetaItemTypeImage = exports.MetaItemTypeText = exports.UsageEventResourceTierCloud = exports.UsageEventResourceTierPrivate = exports.PaymentRecordTypeAutoRecharge = exports.PaymentRecordTypeCheckout = exports.PaymentRecordStatusExpired = exports.PaymentRecordStatusFailed = exports.PaymentRecordStatusComplete = exports.PaymentRecordStatusPending = exports.TransactionTypeDebit = exports.TransactionTypeCredit = exports.ToolInvocationStatusCancelled = exports.ToolInvocationStatusFailed = exports.ToolInvocationStatusCompleted = exports.ToolInvocationStatusAwaitingApproval = exports.ToolInvocationStatusAwaitingInput = exports.ToolInvocationStatusInProgress = exports.ToolInvocationStatusPending = exports.TeamRoleMember = exports.TeamRoleAdmin = exports.TeamRoleOwner = exports.TeamTypeSystem = exports.TeamTypeTeam = exports.TeamTypePersonal = exports.TaskLogTypeTask = exports.TaskLogTypeSetup = exports.TaskLogTypeServe = exports.TaskLogTypeRun = exports.TaskLogTypeBuild = exports.InfraPrivateFirst = exports.InfraCloud = void 0;
|
|
7
|
+
exports.WidgetNodeTypeStatusBadge = exports.WidgetNodeTypeKeyValue = exports.WidgetNodeTypePlanList = exports.WidgetNodeTypeCol = exports.WidgetNodeTypeRow = exports.WidgetNodeTypeCheckbox = exports.WidgetNodeTypeSelect = void 0;
|
|
8
8
|
exports.ToolTypeApp = "app"; // App tools - creates a Task
|
|
9
9
|
exports.ToolTypeAgent = "agent"; // Sub-agent tools - creates a sub-Chat
|
|
10
10
|
exports.ToolTypeHook = "hook"; // Webhook tools - HTTP POST to external URL
|
|
@@ -29,9 +29,7 @@ exports.VisibilityPublic = "public";
|
|
|
29
29
|
exports.VisibilityUnlisted = "unlisted";
|
|
30
30
|
exports.ChatStatusBusy = "busy";
|
|
31
31
|
exports.ChatStatusIdle = "idle";
|
|
32
|
-
|
|
33
|
-
* ChatStatusWaitingInput ChatStatus = "waiting_input"
|
|
34
|
-
*/
|
|
32
|
+
exports.ChatStatusAwaitingInput = "awaiting_input";
|
|
35
33
|
exports.ChatStatusCompleted = "completed";
|
|
36
34
|
exports.PlanStepStatusPending = "pending";
|
|
37
35
|
exports.PlanStepStatusInProgress = "in_progress";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inferencesh/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Official JavaScript/TypeScript SDK for inference.sh - Run AI models with a simple API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "tsc && npm run build:esm",
|
|
17
17
|
"build:esm": "echo 'export * from \"./index.js\";' > dist/index.mjs",
|
|
18
|
-
"test": "jest",
|
|
19
|
-
"test:
|
|
20
|
-
"test:
|
|
18
|
+
"test": "jest --testPathIgnorePatterns=integration",
|
|
19
|
+
"test:integration": "jest --testPathPattern=integration --testTimeout=120000 --runInBand",
|
|
20
|
+
"test:all": "jest --testTimeout=120000 --runInBand",
|
|
21
|
+
"test:watch": "jest --watch --testPathIgnorePatterns=integration",
|
|
22
|
+
"test:coverage": "jest --coverage --testPathIgnorePatterns=integration",
|
|
21
23
|
"lint": "eslint src --ext .ts",
|
|
22
24
|
"lint:fix": "eslint src --ext .ts --fix",
|
|
23
25
|
"format": "prettier --write \"src/**/*.ts\"",
|