illuma-agents 1.0.16 → 1.0.18
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/cjs/agents/AgentContext.cjs +3 -1
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/enum.cjs +18 -0
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +79 -32
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +5 -3
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +1 -0
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs +10 -1
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/llm/vertexai/index.cjs +7 -8
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +15 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +11 -6
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +16 -8
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +9 -2
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/tools.cjs +17 -10
- package/dist/cjs/messages/tools.cjs.map +1 -1
- package/dist/cjs/stream.cjs +30 -16
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +209 -47
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +73 -3
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +1 -0
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +3 -1
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/utils/contextAnalytics.cjs +66 -0
- package/dist/cjs/utils/contextAnalytics.cjs.map +1 -0
- package/dist/cjs/utils/run.cjs.map +1 -1
- package/dist/cjs/utils/toonFormat.cjs +388 -0
- package/dist/cjs/utils/toonFormat.cjs.map +1 -0
- package/dist/esm/agents/AgentContext.mjs +3 -1
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/enum.mjs +19 -1
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +81 -34
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +5 -3
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +1 -0
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs +10 -1
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/llm/vertexai/index.mjs +7 -8
- package/dist/esm/llm/vertexai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +4 -2
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/messages/cache.mjs +11 -6
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +18 -10
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +10 -3
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/tools.mjs +19 -12
- package/dist/esm/messages/tools.mjs.map +1 -1
- package/dist/esm/stream.mjs +30 -16
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +208 -48
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +73 -3
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +1 -0
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +3 -1
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/utils/contextAnalytics.mjs +64 -0
- package/dist/esm/utils/contextAnalytics.mjs.map +1 -0
- package/dist/esm/utils/run.mjs.map +1 -1
- package/dist/esm/utils/toonFormat.mjs +381 -0
- package/dist/esm/utils/toonFormat.mjs.map +1 -0
- package/dist/types/common/enum.d.ts +17 -0
- package/dist/types/graphs/Graph.d.ts +8 -0
- package/dist/types/tools/ProgrammaticToolCalling.d.ts +19 -0
- package/dist/types/types/tools.d.ts +3 -1
- package/dist/types/utils/contextAnalytics.d.ts +37 -0
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/toonFormat.d.ts +111 -0
- package/package.json +3 -2
- package/src/agents/AgentContext.ts +28 -20
- package/src/common/enum.ts +18 -0
- package/src/graphs/Graph.ts +152 -62
- package/src/llm/bedrock/__tests__/bedrock-caching.test.ts +495 -473
- package/src/llm/bedrock/index.ts +47 -35
- package/src/llm/openrouter/index.ts +11 -1
- package/src/llm/vertexai/index.ts +9 -10
- package/src/messages/cache.ts +104 -55
- package/src/messages/core.ts +29 -19
- package/src/messages/format.ts +14 -3
- package/src/messages/tools.ts +20 -13
- package/src/scripts/simple.ts +1 -1
- package/src/specs/emergency-prune.test.ts +407 -355
- package/src/stream.ts +28 -20
- package/src/tools/ProgrammaticToolCalling.ts +246 -52
- package/src/tools/ToolNode.ts +78 -5
- package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +155 -0
- package/src/tools/search/jina-reranker.test.ts +32 -28
- package/src/tools/search/search.ts +3 -1
- package/src/tools/search/tool.ts +16 -7
- package/src/types/tools.ts +3 -1
- package/src/utils/contextAnalytics.ts +103 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/llmConfig.ts +8 -1
- package/src/utils/run.ts +5 -4
- package/src/utils/toonFormat.ts +475 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Analytics Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides context analytics data for observability/traces.
|
|
5
|
+
* No console logging - just data structures for event emission.
|
|
6
|
+
*/
|
|
7
|
+
import type { BaseMessage } from '@langchain/core/messages';
|
|
8
|
+
import type { TokenCounter } from '@/types/run';
|
|
9
|
+
/**
|
|
10
|
+
* Context analytics data for traces
|
|
11
|
+
*/
|
|
12
|
+
export interface ContextAnalytics {
|
|
13
|
+
/** Total messages in context */
|
|
14
|
+
messageCount: number;
|
|
15
|
+
/** Total tokens in context */
|
|
16
|
+
totalTokens: number;
|
|
17
|
+
/** Maximum allowed context tokens */
|
|
18
|
+
maxContextTokens?: number;
|
|
19
|
+
/** Instruction/system tokens */
|
|
20
|
+
instructionTokens?: number;
|
|
21
|
+
/** Context utilization percentage (0-100) */
|
|
22
|
+
utilizationPercent?: number;
|
|
23
|
+
/** Breakdown by message type */
|
|
24
|
+
breakdown?: Record<string, {
|
|
25
|
+
tokens: number;
|
|
26
|
+
percent: number;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Build context analytics for traces (no logging)
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildContextAnalytics(messages: BaseMessage[], options: {
|
|
33
|
+
tokenCounter?: TokenCounter;
|
|
34
|
+
maxContextTokens?: number;
|
|
35
|
+
instructionTokens?: number;
|
|
36
|
+
indexTokenCountMap?: Record<string, number | undefined>;
|
|
37
|
+
}): ContextAnalytics;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TOON Format Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides JSON to TOON conversion for token-efficient encoding.
|
|
5
|
+
* TOON format can reduce token count by 30-60% for JSON data.
|
|
6
|
+
*
|
|
7
|
+
* Uses the official @toon-format/toon library when available.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Ensures the TOON library is loaded. Call this before using jsonToToon in tests.
|
|
11
|
+
*/
|
|
12
|
+
export declare function ensureToonLoaded(): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Check if a string appears to be in TOON format.
|
|
15
|
+
* TOON format characteristics:
|
|
16
|
+
* - Uses key: value syntax (like YAML)
|
|
17
|
+
* - Uses array notation like [3] or {fields}
|
|
18
|
+
* - Does NOT start with { or [
|
|
19
|
+
* - Often has patterns like "name[N]:" or "name{fields}:"
|
|
20
|
+
*
|
|
21
|
+
* @param str - String to check
|
|
22
|
+
* @returns true if string appears to be TOON format
|
|
23
|
+
*/
|
|
24
|
+
export declare function isToonFormat(str: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Extract the first valid JSON object or array from a string.
|
|
27
|
+
* Handles pure JSON or JSON embedded in text (e.g., tool responses).
|
|
28
|
+
*
|
|
29
|
+
* @param str - The string to extract JSON from
|
|
30
|
+
* @returns Object with found status, parsed JSON, and indices
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractFirstJson(str: string): {
|
|
33
|
+
found: boolean;
|
|
34
|
+
parsed: unknown;
|
|
35
|
+
startIndex: number;
|
|
36
|
+
endIndex: number;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Convert JSON content to TOON format for token efficiency.
|
|
40
|
+
* Extracts JSON from string if embedded, converts to TOON.
|
|
41
|
+
* Returns original string if:
|
|
42
|
+
* - Already in TOON format
|
|
43
|
+
* - Not JSON
|
|
44
|
+
* - TOON conversion fails or is larger
|
|
45
|
+
*
|
|
46
|
+
* @param str - The string containing JSON to convert
|
|
47
|
+
* @returns Object with conversion status, result, and reduction percentage
|
|
48
|
+
*/
|
|
49
|
+
export declare function jsonToToon(str: string): {
|
|
50
|
+
converted: boolean;
|
|
51
|
+
result: string;
|
|
52
|
+
reduction: number;
|
|
53
|
+
alreadyToon?: boolean;
|
|
54
|
+
error?: string;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Check if TOON library is loaded and available
|
|
58
|
+
*/
|
|
59
|
+
export declare function isToonAvailable(): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Result of processing tool output
|
|
62
|
+
*/
|
|
63
|
+
export interface ProcessToolOutputResult {
|
|
64
|
+
/** The processed content string */
|
|
65
|
+
content: string;
|
|
66
|
+
/** Whether TOON conversion was applied */
|
|
67
|
+
toonConverted: boolean;
|
|
68
|
+
/** Whether content was truncated */
|
|
69
|
+
truncated: boolean;
|
|
70
|
+
/** Percentage reduction from TOON (0 if not converted) */
|
|
71
|
+
reduction: number;
|
|
72
|
+
/** Whether input was already in TOON format */
|
|
73
|
+
alreadyToon: boolean;
|
|
74
|
+
/** Original content length */
|
|
75
|
+
originalLength: number;
|
|
76
|
+
/** Estimated original tokens (~4 chars per token) */
|
|
77
|
+
originalTokens: number;
|
|
78
|
+
/** Final content length */
|
|
79
|
+
finalLength: number;
|
|
80
|
+
/** Estimated final tokens */
|
|
81
|
+
finalTokens: number;
|
|
82
|
+
/** Error message if TOON conversion failed (for debugging) */
|
|
83
|
+
toonError?: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Options for processing tool output
|
|
87
|
+
*/
|
|
88
|
+
export interface ProcessToolOutputOptions {
|
|
89
|
+
/** Maximum output length in characters (default: 100000) */
|
|
90
|
+
maxLength?: number;
|
|
91
|
+
/** Whether to apply TOON conversion (default: true) */
|
|
92
|
+
enableToon?: boolean;
|
|
93
|
+
/** Minimum content size to attempt TOON conversion (default: 1000) */
|
|
94
|
+
minSizeForToon?: number;
|
|
95
|
+
/** Minimum reduction % to accept TOON result (default: 10) */
|
|
96
|
+
minReductionPercent?: number;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Process tool output: apply TOON conversion if beneficial, then truncate if needed.
|
|
100
|
+
* This is the main entry point for processing any tool output (regular or MCP).
|
|
101
|
+
*
|
|
102
|
+
* Flow:
|
|
103
|
+
* 1. Check if already TOON format → skip conversion
|
|
104
|
+
* 2. Try TOON conversion if content is JSON and large enough
|
|
105
|
+
* 3. Truncate if still exceeds maxLength (with smart break points)
|
|
106
|
+
*
|
|
107
|
+
* @param content - The tool output content
|
|
108
|
+
* @param options - Processing options
|
|
109
|
+
* @returns Processed content and metadata
|
|
110
|
+
*/
|
|
111
|
+
export declare function processToolOutput(content: string, options?: ProcessToolOutputOptions): ProcessToolOutputResult;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "illuma-agents",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.18",
|
|
4
4
|
"main": "./dist/cjs/main.cjs",
|
|
5
5
|
"module": "./dist/esm/main.mjs",
|
|
6
6
|
"types": "./dist/types/index.d.ts",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"image": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/image.ts --provider 'google' --name 'Jo' --location 'New York, NY'",
|
|
42
42
|
"code_exec_files": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/code_exec_files.ts --provider 'openAI' --name 'Jo' --location 'New York, NY'",
|
|
43
43
|
"code_exec_simple": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/code_exec_simple.ts --provider 'google' --name 'Jo' --location 'New York, NY'",
|
|
44
|
-
"simple": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/simple.ts --provider '
|
|
44
|
+
"simple": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/simple.ts --provider 'openrouter' --name 'Jo' --location 'New York, NY'",
|
|
45
45
|
"caching": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/caching.ts --name 'Jo' --location 'New York, NY'",
|
|
46
46
|
"thinking": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/thinking.ts --name 'Jo' --location 'New York, NY'",
|
|
47
47
|
"memory": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/memory.ts --provider 'openAI' --name 'Jo' --location 'New York, NY'",
|
|
@@ -111,6 +111,7 @@
|
|
|
111
111
|
"@langfuse/otel": "^4.3.0",
|
|
112
112
|
"@langfuse/tracing": "^4.3.0",
|
|
113
113
|
"@opentelemetry/sdk-node": "^0.207.0",
|
|
114
|
+
"@toon-format/toon": "^2.1.0",
|
|
114
115
|
"axios": "^1.12.1",
|
|
115
116
|
"cheerio": "^1.0.0",
|
|
116
117
|
"dotenv": "^16.4.7",
|
|
@@ -166,13 +166,13 @@ export class AgentContext {
|
|
|
166
166
|
artifacts: number;
|
|
167
167
|
memory: number;
|
|
168
168
|
} = {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
169
|
+
branding: 0,
|
|
170
|
+
toolRouting: 0,
|
|
171
|
+
agentInstructions: 0,
|
|
172
|
+
mcpInstructions: 0,
|
|
173
|
+
artifacts: 0,
|
|
174
|
+
memory: 0,
|
|
175
|
+
};
|
|
176
176
|
|
|
177
177
|
constructor({
|
|
178
178
|
agentId,
|
|
@@ -403,10 +403,12 @@ export class AgentContext {
|
|
|
403
403
|
| t.BedrockAnthropicInput
|
|
404
404
|
| undefined;
|
|
405
405
|
const modelId = bedrockOptions?.model?.toLowerCase() ?? '';
|
|
406
|
-
const supportsCaching =
|
|
406
|
+
const supportsCaching =
|
|
407
|
+
modelId.includes('claude') ||
|
|
408
|
+
modelId.includes('anthropic') ||
|
|
409
|
+
modelId.includes('nova');
|
|
407
410
|
|
|
408
411
|
if (bedrockOptions?.promptCache === true && supportsCaching) {
|
|
409
|
-
|
|
410
412
|
finalInstructions = {
|
|
411
413
|
content: [
|
|
412
414
|
{
|
|
@@ -485,7 +487,7 @@ export class AgentContext {
|
|
|
485
487
|
): Promise<void> {
|
|
486
488
|
let toolTokens = 0;
|
|
487
489
|
this.toolsDetail = []; // Reset per-tool breakdown
|
|
488
|
-
|
|
490
|
+
|
|
489
491
|
if (this.tools && this.tools.length > 0) {
|
|
490
492
|
for (const tool of this.tools) {
|
|
491
493
|
const genericTool = tool as Record<string, unknown>;
|
|
@@ -507,7 +509,7 @@ export class AgentContext {
|
|
|
507
509
|
const tokens = tokenCounter(
|
|
508
510
|
new SystemMessage(JSON.stringify(jsonSchema))
|
|
509
511
|
);
|
|
510
|
-
|
|
512
|
+
|
|
511
513
|
// Track per-tool breakdown
|
|
512
514
|
this.toolsDetail.push({ name: toolName, tokens });
|
|
513
515
|
toolTokens += tokens;
|
|
@@ -517,7 +519,7 @@ export class AgentContext {
|
|
|
517
519
|
|
|
518
520
|
// Store total tool tokens for breakdown reporting
|
|
519
521
|
this.toolTokensTotal = toolTokens;
|
|
520
|
-
|
|
522
|
+
|
|
521
523
|
// Add tool tokens to existing instruction tokens (which may already include system message tokens)
|
|
522
524
|
this.instructionTokens += toolTokens;
|
|
523
525
|
}
|
|
@@ -535,12 +537,18 @@ export class AgentContext {
|
|
|
535
537
|
artifacts?: number;
|
|
536
538
|
memory?: number;
|
|
537
539
|
}): void {
|
|
538
|
-
if (breakdown.branding !== undefined)
|
|
539
|
-
|
|
540
|
-
if (breakdown.
|
|
541
|
-
|
|
542
|
-
if (breakdown.
|
|
543
|
-
|
|
540
|
+
if (breakdown.branding !== undefined)
|
|
541
|
+
this.promptBreakdown.branding = breakdown.branding;
|
|
542
|
+
if (breakdown.toolRouting !== undefined)
|
|
543
|
+
this.promptBreakdown.toolRouting = breakdown.toolRouting;
|
|
544
|
+
if (breakdown.agentInstructions !== undefined)
|
|
545
|
+
this.promptBreakdown.agentInstructions = breakdown.agentInstructions;
|
|
546
|
+
if (breakdown.mcpInstructions !== undefined)
|
|
547
|
+
this.promptBreakdown.mcpInstructions = breakdown.mcpInstructions;
|
|
548
|
+
if (breakdown.artifacts !== undefined)
|
|
549
|
+
this.promptBreakdown.artifacts = breakdown.artifacts;
|
|
550
|
+
if (breakdown.memory !== undefined)
|
|
551
|
+
this.promptBreakdown.memory = breakdown.memory;
|
|
544
552
|
}
|
|
545
553
|
|
|
546
554
|
/**
|
|
@@ -565,9 +573,9 @@ export class AgentContext {
|
|
|
565
573
|
artifacts: number;
|
|
566
574
|
memory: number;
|
|
567
575
|
};
|
|
568
|
-
|
|
576
|
+
} {
|
|
569
577
|
// Calculate sum of prompt components
|
|
570
|
-
const promptsTotal =
|
|
578
|
+
const promptsTotal =
|
|
571
579
|
this.promptBreakdown.branding +
|
|
572
580
|
this.promptBreakdown.toolRouting +
|
|
573
581
|
this.promptBreakdown.agentInstructions +
|
package/src/common/enum.ts
CHANGED
|
@@ -19,6 +19,8 @@ export enum GraphEvents {
|
|
|
19
19
|
ON_MESSAGE_DELTA = 'on_message_delta',
|
|
20
20
|
/** [Custom] Reasoning Delta events for messages */
|
|
21
21
|
ON_REASONING_DELTA = 'on_reasoning_delta',
|
|
22
|
+
/** [Custom] Context analytics event for traces */
|
|
23
|
+
ON_CONTEXT_ANALYTICS = 'on_context_analytics',
|
|
22
24
|
|
|
23
25
|
/* Official Events */
|
|
24
26
|
|
|
@@ -176,3 +178,19 @@ export enum EnvVar {
|
|
|
176
178
|
CODE_API_KEY = 'CODE_EXECUTOR_API_KEY',
|
|
177
179
|
CODE_BASEURL = 'CODE_EXECUTOR_BASEURL',
|
|
178
180
|
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Message type identifiers used by LangChain's BaseMessage.getType().
|
|
184
|
+
* Use these constants instead of instanceof checks to avoid module mismatch issues
|
|
185
|
+
* when different copies of @langchain/core/messages are loaded.
|
|
186
|
+
*/
|
|
187
|
+
export enum MessageTypes {
|
|
188
|
+
HUMAN = 'human',
|
|
189
|
+
AI = 'ai',
|
|
190
|
+
SYSTEM = 'system',
|
|
191
|
+
TOOL = 'tool',
|
|
192
|
+
FUNCTION = 'function',
|
|
193
|
+
GENERIC = 'generic',
|
|
194
|
+
DEVELOPER = 'developer',
|
|
195
|
+
REMOVE = 'remove',
|
|
196
|
+
}
|