@kindgi/dev-echo-provider 0.1.4-rc.3 → 0.1.4-rc.4
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 +13 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +47 -2
package/README.md
CHANGED
|
@@ -14,6 +14,19 @@ Emits a two-message script (tool-call → text):
|
|
|
14
14
|
2. **Second invocation** (post-tool) — emits a final assistant message:
|
|
15
15
|
`Tool responded: <tool result>`.
|
|
16
16
|
|
|
17
|
+
**It says it isn't a model.** Every text answer starts with one line,
|
|
18
|
+
`DEV_ECHO_WARNING_LINE`:
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
⚠ dev-echo isn't a real model: it only repeats what it's given. Add an LLM provider key (Anthropic, OpenAI, Gemini, Groq, OpenRouter…) to get real answers.
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
An answer that is JSON (what a typed-output agent parses; dev-echo hands
|
|
25
|
+
back the JSON it was given) stays bare, as does one asked for with
|
|
26
|
+
`structuredOutput`. Every result also carries `warnings: [DEV_ECHO_WARNING]`
|
|
27
|
+
(code `dev-echo-not-a-model`, with the commands that add a model), which an
|
|
28
|
+
agent turn collects into its result's `warnings`.
|
|
29
|
+
|
|
17
30
|
State lives in the message trail, not on the instance — safe to share
|
|
18
31
|
across concurrent runs.
|
|
19
32
|
|
package/dist/index.d.ts
CHANGED
|
@@ -15,14 +15,29 @@
|
|
|
15
15
|
* itself — so a typed-output agent handed JSON gets that JSON back.
|
|
16
16
|
* - On the second invocation (post-tool) it emits a final assistant
|
|
17
17
|
* message: `Tool responded: <tool result>`.
|
|
18
|
+
* - Every text answer starts with `DEV_ECHO_WARNING_LINE`, and every
|
|
19
|
+
* result carries `DEV_ECHO_WARNING` (`dev-echo-not-a-model`), so no one
|
|
20
|
+
* mistakes it for a model. A JSON answer (what a typed-output agent
|
|
21
|
+
* parses) and a `structuredOutput` one stay bare.
|
|
18
22
|
*
|
|
19
23
|
* State lives per-invocation — the provider inspects the message trail,
|
|
20
24
|
* not an instance variable, so it is safe to share across concurrent
|
|
21
25
|
* runs.
|
|
22
26
|
*/
|
|
23
|
-
import type { ModelProvider, ProviderMetadata } from '@kindgi/capabilities';
|
|
27
|
+
import type { ModelCallWarning, ModelProvider, ProviderMetadata } from '@kindgi/capabilities';
|
|
24
28
|
export declare const DEV_ECHO_PROVIDER_ID = "dev-echo";
|
|
25
29
|
export declare const DEV_ECHO_MODEL_NAME = "dev-echo-v1";
|
|
30
|
+
/** The code of the warning every dev-echo answer carries (`ModelCallResult.warnings`). */
|
|
31
|
+
export declare const DEV_ECHO_WARNING_CODE = "dev-echo-not-a-model";
|
|
32
|
+
/**
|
|
33
|
+
* The first line of every dev-echo text answer: it isn't a model, and what
|
|
34
|
+
* to do. A JSON answer stays bare (a typed-output agent parses it: echo
|
|
35
|
+
* hands back the JSON it was given), as does one asked for with
|
|
36
|
+
* `structuredOutput`; the warning in `warnings` says the same there.
|
|
37
|
+
*/
|
|
38
|
+
export declare const DEV_ECHO_WARNING_LINE = "\u26A0 dev-echo isn't a real model: it only repeats what it's given. Add an LLM provider key (Anthropic, OpenAI, Gemini, Groq, OpenRouter\u2026) to get real answers.";
|
|
39
|
+
/** The warning, with the commands that add a model. */
|
|
40
|
+
export declare const DEV_ECHO_WARNING: ModelCallWarning;
|
|
26
41
|
/**
|
|
27
42
|
* Build the deterministic dev-echo provider. The returned value is a
|
|
28
43
|
* plain `ModelProvider` — pass it to `createProviderRegistry([...])` or
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAGV,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EACjB,MAAM,sBAAsB,CAAC;AAE9B,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAC/C,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAuBjD,0FAA0F;AAC1F,eAAO,MAAM,qBAAqB,yBAAyB,CAAC;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,0KAC6H,CAAC;AAEhK,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,EAAE,gBAI9B,CAAC;AAoCF;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,aAAa,CAqDrD;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,gBAA2B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,39 @@ const METADATA = {
|
|
|
20
20
|
fallback: true,
|
|
21
21
|
};
|
|
22
22
|
const TOOL_CALL_ID = 'dev-echo-call-1';
|
|
23
|
+
/** The code of the warning every dev-echo answer carries (`ModelCallResult.warnings`). */
|
|
24
|
+
export const DEV_ECHO_WARNING_CODE = 'dev-echo-not-a-model';
|
|
25
|
+
/**
|
|
26
|
+
* The first line of every dev-echo text answer: it isn't a model, and what
|
|
27
|
+
* to do. A JSON answer stays bare (a typed-output agent parses it: echo
|
|
28
|
+
* hands back the JSON it was given), as does one asked for with
|
|
29
|
+
* `structuredOutput`; the warning in `warnings` says the same there.
|
|
30
|
+
*/
|
|
31
|
+
export const DEV_ECHO_WARNING_LINE = "⚠ dev-echo isn't a real model: it only repeats what it's given. Add an LLM provider key (Anthropic, OpenAI, Gemini, Groq, OpenRouter…) to get real answers.";
|
|
32
|
+
/** The warning, with the commands that add a model. */
|
|
33
|
+
export const DEV_ECHO_WARNING = {
|
|
34
|
+
code: DEV_ECHO_WARNING_CODE,
|
|
35
|
+
message: "dev-echo answered, and it isn't a real model: it only repeats what it's given. Add an LLM provider key: kindgi secrets set <KEY> --env=local --scope=tenant (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, GROQ_API_KEY, OPENROUTER_API_KEY…), then kindgi providers register --preset=<anthropic|openai|gemini-api|groq|openrouter>. kindgi providers presets lists them.",
|
|
36
|
+
};
|
|
37
|
+
/** An answer that is a JSON object or array: what a typed-output agent parses. */
|
|
38
|
+
function isJsonAnswer(text) {
|
|
39
|
+
const t = text.trim();
|
|
40
|
+
if (!(t.startsWith('{') || t.startsWith('[')))
|
|
41
|
+
return false;
|
|
42
|
+
try {
|
|
43
|
+
JSON.parse(t);
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** A text answer, with the warning line first; a typed (JSON) answer as it is. */
|
|
51
|
+
function answerText(input, text) {
|
|
52
|
+
if (input.structuredOutput !== undefined || isJsonAnswer(text))
|
|
53
|
+
return text;
|
|
54
|
+
return `${DEV_ECHO_WARNING_LINE}\n\n${text}`;
|
|
55
|
+
}
|
|
23
56
|
function lastUserMessage(input) {
|
|
24
57
|
for (let i = input.messages.length - 1; i >= 0; i -= 1) {
|
|
25
58
|
const m = input.messages[i];
|
|
@@ -49,12 +82,13 @@ export function createDevEchoProvider() {
|
|
|
49
82
|
const toolName = input.tools?.[0]?.name;
|
|
50
83
|
if (toolResult === null && toolName === undefined) {
|
|
51
84
|
return {
|
|
52
|
-
message: { role: 'assistant', content: lastUserMessage(input) },
|
|
85
|
+
message: { role: 'assistant', content: answerText(input, lastUserMessage(input)) },
|
|
53
86
|
finishReason: 'stop',
|
|
54
87
|
usage: { promptTokens: 20, completionTokens: 6 },
|
|
55
88
|
costUsd: 0,
|
|
56
89
|
durationMs: 1,
|
|
57
90
|
provider: { id: METADATA.id, model: DEV_ECHO_MODEL_NAME },
|
|
91
|
+
warnings: [DEV_ECHO_WARNING],
|
|
58
92
|
};
|
|
59
93
|
}
|
|
60
94
|
if (toolResult === null && toolName !== undefined) {
|
|
@@ -76,18 +110,20 @@ export function createDevEchoProvider() {
|
|
|
76
110
|
costUsd: 0,
|
|
77
111
|
durationMs: 1,
|
|
78
112
|
provider: { id: METADATA.id, model: DEV_ECHO_MODEL_NAME },
|
|
113
|
+
warnings: [DEV_ECHO_WARNING],
|
|
79
114
|
};
|
|
80
115
|
}
|
|
81
116
|
return {
|
|
82
117
|
message: {
|
|
83
118
|
role: 'assistant',
|
|
84
|
-
content: `Tool responded: ${toolResult}
|
|
119
|
+
content: answerText(input, `Tool responded: ${toolResult}`),
|
|
85
120
|
},
|
|
86
121
|
finishReason: 'stop',
|
|
87
122
|
usage: { promptTokens: 30, completionTokens: 12 },
|
|
88
123
|
costUsd: 0,
|
|
89
124
|
durationMs: 1,
|
|
90
125
|
provider: { id: METADATA.id, model: DEV_ECHO_MODEL_NAME },
|
|
126
|
+
warnings: [DEV_ECHO_WARNING],
|
|
91
127
|
};
|
|
92
128
|
},
|
|
93
129
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kindgi/dev-echo-provider",
|
|
3
|
-
"version": "0.1.4-rc.
|
|
3
|
+
"version": "0.1.4-rc.4",
|
|
4
4
|
"description": "Deterministic dev-only ModelProvider — no LLM key, no network, no cost. Emits a two-message scripted response (tool-call → text) so an agent turn completes in milliseconds. For dev, tests and tutorials. NEVER for production — every real deployment plugs in a real model provider adapter (Anthropic, OpenAI-compat, etc.) instead.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"README.md"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@kindgi/capabilities": "0.1.4-rc.
|
|
31
|
+
"@kindgi/capabilities": "0.1.4-rc.4"
|
|
32
32
|
},
|
|
33
33
|
"engines": {
|
|
34
34
|
"node": ">=22.12.0"
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
* itself — so a typed-output agent handed JSON gets that JSON back.
|
|
19
19
|
* - On the second invocation (post-tool) it emits a final assistant
|
|
20
20
|
* message: `Tool responded: <tool result>`.
|
|
21
|
+
* - Every text answer starts with `DEV_ECHO_WARNING_LINE`, and every
|
|
22
|
+
* result carries `DEV_ECHO_WARNING` (`dev-echo-not-a-model`), so no one
|
|
23
|
+
* mistakes it for a model. A JSON answer (what a typed-output agent
|
|
24
|
+
* parses) and a `structuredOutput` one stay bare.
|
|
21
25
|
*
|
|
22
26
|
* State lives per-invocation — the provider inspects the message trail,
|
|
23
27
|
* not an instance variable, so it is safe to share across concurrent
|
|
@@ -27,6 +31,7 @@
|
|
|
27
31
|
import type {
|
|
28
32
|
ModelCallInput,
|
|
29
33
|
ModelCallResult,
|
|
34
|
+
ModelCallWarning,
|
|
30
35
|
ModelProvider,
|
|
31
36
|
ProviderMetadata,
|
|
32
37
|
} from '@kindgi/capabilities';
|
|
@@ -55,6 +60,43 @@ const METADATA: ProviderMetadata = {
|
|
|
55
60
|
|
|
56
61
|
const TOOL_CALL_ID = 'dev-echo-call-1';
|
|
57
62
|
|
|
63
|
+
/** The code of the warning every dev-echo answer carries (`ModelCallResult.warnings`). */
|
|
64
|
+
export const DEV_ECHO_WARNING_CODE = 'dev-echo-not-a-model';
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The first line of every dev-echo text answer: it isn't a model, and what
|
|
68
|
+
* to do. A JSON answer stays bare (a typed-output agent parses it: echo
|
|
69
|
+
* hands back the JSON it was given), as does one asked for with
|
|
70
|
+
* `structuredOutput`; the warning in `warnings` says the same there.
|
|
71
|
+
*/
|
|
72
|
+
export const DEV_ECHO_WARNING_LINE =
|
|
73
|
+
"⚠ dev-echo isn't a real model: it only repeats what it's given. Add an LLM provider key (Anthropic, OpenAI, Gemini, Groq, OpenRouter…) to get real answers.";
|
|
74
|
+
|
|
75
|
+
/** The warning, with the commands that add a model. */
|
|
76
|
+
export const DEV_ECHO_WARNING: ModelCallWarning = {
|
|
77
|
+
code: DEV_ECHO_WARNING_CODE,
|
|
78
|
+
message:
|
|
79
|
+
"dev-echo answered, and it isn't a real model: it only repeats what it's given. Add an LLM provider key: kindgi secrets set <KEY> --env=local --scope=tenant (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, GROQ_API_KEY, OPENROUTER_API_KEY…), then kindgi providers register --preset=<anthropic|openai|gemini-api|groq|openrouter>. kindgi providers presets lists them.",
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/** An answer that is a JSON object or array: what a typed-output agent parses. */
|
|
83
|
+
function isJsonAnswer(text: string): boolean {
|
|
84
|
+
const t = text.trim();
|
|
85
|
+
if (!(t.startsWith('{') || t.startsWith('['))) return false;
|
|
86
|
+
try {
|
|
87
|
+
JSON.parse(t);
|
|
88
|
+
return true;
|
|
89
|
+
} catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** A text answer, with the warning line first; a typed (JSON) answer as it is. */
|
|
95
|
+
function answerText(input: ModelCallInput, text: string): string {
|
|
96
|
+
if (input.structuredOutput !== undefined || isJsonAnswer(text)) return text;
|
|
97
|
+
return `${DEV_ECHO_WARNING_LINE}\n\n${text}`;
|
|
98
|
+
}
|
|
99
|
+
|
|
58
100
|
function lastUserMessage(input: ModelCallInput): string {
|
|
59
101
|
for (let i = input.messages.length - 1; i >= 0; i -= 1) {
|
|
60
102
|
const m = input.messages[i];
|
|
@@ -84,12 +126,13 @@ export function createDevEchoProvider(): ModelProvider {
|
|
|
84
126
|
const toolName = input.tools?.[0]?.name;
|
|
85
127
|
if (toolResult === null && toolName === undefined) {
|
|
86
128
|
return {
|
|
87
|
-
message: { role: 'assistant', content: lastUserMessage(input) },
|
|
129
|
+
message: { role: 'assistant', content: answerText(input, lastUserMessage(input)) },
|
|
88
130
|
finishReason: 'stop',
|
|
89
131
|
usage: { promptTokens: 20, completionTokens: 6 },
|
|
90
132
|
costUsd: 0,
|
|
91
133
|
durationMs: 1,
|
|
92
134
|
provider: { id: METADATA.id, model: DEV_ECHO_MODEL_NAME },
|
|
135
|
+
warnings: [DEV_ECHO_WARNING],
|
|
93
136
|
};
|
|
94
137
|
}
|
|
95
138
|
if (toolResult === null && toolName !== undefined) {
|
|
@@ -111,18 +154,20 @@ export function createDevEchoProvider(): ModelProvider {
|
|
|
111
154
|
costUsd: 0,
|
|
112
155
|
durationMs: 1,
|
|
113
156
|
provider: { id: METADATA.id, model: DEV_ECHO_MODEL_NAME },
|
|
157
|
+
warnings: [DEV_ECHO_WARNING],
|
|
114
158
|
};
|
|
115
159
|
}
|
|
116
160
|
return {
|
|
117
161
|
message: {
|
|
118
162
|
role: 'assistant',
|
|
119
|
-
content: `Tool responded: ${toolResult}
|
|
163
|
+
content: answerText(input, `Tool responded: ${toolResult}`),
|
|
120
164
|
},
|
|
121
165
|
finishReason: 'stop',
|
|
122
166
|
usage: { promptTokens: 30, completionTokens: 12 },
|
|
123
167
|
costUsd: 0,
|
|
124
168
|
durationMs: 1,
|
|
125
169
|
provider: { id: METADATA.id, model: DEV_ECHO_MODEL_NAME },
|
|
170
|
+
warnings: [DEV_ECHO_WARNING],
|
|
126
171
|
};
|
|
127
172
|
},
|
|
128
173
|
};
|