@ebowwa/ai 0.1.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/LICENSE +21 -0
- package/README.md +106 -0
- package/dist/client.d.ts +179 -0
- package/dist/client.js +492 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +18 -0
- package/dist/prompts.d.ts +222 -0
- package/dist/prompts.js +462 -0
- package/dist/schemas/ai.d.ts +1335 -0
- package/dist/schemas/ai.js +416 -0
- package/dist/schemas/glm.d.ts +16 -0
- package/dist/schemas/glm.js +25 -0
- package/dist/schemas/index.d.ts +5 -0
- package/dist/schemas/index.js +5 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.js +13 -0
- package/package.json +78 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composable prompt architecture for scalable AI interactions
|
|
3
|
+
*
|
|
4
|
+
* Core concepts:
|
|
5
|
+
* - PromptPart: Composable building blocks
|
|
6
|
+
* - PromptBuilder: Fluent API for assembling prompts
|
|
7
|
+
* - PromptTemplate: Reusable templates with interpolation
|
|
8
|
+
* - PromptChain: Multi-step workflows
|
|
9
|
+
* - PromptStrategy: Different reasoning approaches
|
|
10
|
+
*/
|
|
11
|
+
import type { ChatMessage } from "./types.js";
|
|
12
|
+
export type { ChatMessage };
|
|
13
|
+
/**
|
|
14
|
+
* Base interface for all composable prompt parts
|
|
15
|
+
*/
|
|
16
|
+
export interface PromptPart {
|
|
17
|
+
toPrompt(): string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* System instruction - sets AI role and behavior
|
|
21
|
+
*/
|
|
22
|
+
export declare class SystemInstruction implements PromptPart {
|
|
23
|
+
role: string;
|
|
24
|
+
guidelines?: string[] | undefined;
|
|
25
|
+
constructor(role: string, guidelines?: string[] | undefined);
|
|
26
|
+
toPrompt(): string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Context - provides data/background information
|
|
30
|
+
*/
|
|
31
|
+
export declare class Context implements PromptPart {
|
|
32
|
+
data: Record<string, unknown>;
|
|
33
|
+
constructor(data: Record<string, unknown>);
|
|
34
|
+
toPrompt(): string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Examples - few-shot learning samples
|
|
38
|
+
*/
|
|
39
|
+
export declare class Examples implements PromptPart {
|
|
40
|
+
examples: Array<{
|
|
41
|
+
input: string;
|
|
42
|
+
output: string;
|
|
43
|
+
}>;
|
|
44
|
+
constructor(examples: Array<{
|
|
45
|
+
input: string;
|
|
46
|
+
output: string;
|
|
47
|
+
}>);
|
|
48
|
+
toPrompt(): string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Output format specification
|
|
52
|
+
*/
|
|
53
|
+
export declare class OutputFormat implements PromptPart {
|
|
54
|
+
type: "json" | "text" | "code" | "markdown";
|
|
55
|
+
schema?: Record<string, unknown> | undefined;
|
|
56
|
+
constructor(type: "json" | "text" | "code" | "markdown", schema?: Record<string, unknown> | undefined);
|
|
57
|
+
toPrompt(): string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Constraints - rules and limitations
|
|
61
|
+
*/
|
|
62
|
+
export declare class Constraints implements PromptPart {
|
|
63
|
+
rules: string[];
|
|
64
|
+
constructor(rules: string[]);
|
|
65
|
+
toPrompt(): string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Task - the main instruction/question
|
|
69
|
+
*/
|
|
70
|
+
export declare class Task implements PromptPart {
|
|
71
|
+
instruction: string;
|
|
72
|
+
constructor(instruction: string);
|
|
73
|
+
toPrompt(): string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Fluent builder for composable prompts
|
|
77
|
+
*/
|
|
78
|
+
export declare class PromptBuilder {
|
|
79
|
+
private parts;
|
|
80
|
+
private systemPart?;
|
|
81
|
+
/**
|
|
82
|
+
* Set system role and guidelines
|
|
83
|
+
*/
|
|
84
|
+
system(role: string, guidelines?: string[]): this;
|
|
85
|
+
/**
|
|
86
|
+
* Add context data
|
|
87
|
+
*/
|
|
88
|
+
context(data: Record<string, unknown>): this;
|
|
89
|
+
/**
|
|
90
|
+
* Add few-shot examples
|
|
91
|
+
*/
|
|
92
|
+
examples(examples: Array<{
|
|
93
|
+
input: string;
|
|
94
|
+
output: string;
|
|
95
|
+
}>): this;
|
|
96
|
+
/**
|
|
97
|
+
* Specify output format
|
|
98
|
+
*/
|
|
99
|
+
output(type: "json" | "text" | "code" | "markdown", schema?: Record<string, unknown>): this;
|
|
100
|
+
/**
|
|
101
|
+
* Add constraints/rules
|
|
102
|
+
*/
|
|
103
|
+
constraints(...rules: string[]): this;
|
|
104
|
+
/**
|
|
105
|
+
* Add the main task/instruction
|
|
106
|
+
*/
|
|
107
|
+
task(instruction: string): this;
|
|
108
|
+
/**
|
|
109
|
+
* Add custom prompt part
|
|
110
|
+
*/
|
|
111
|
+
custom(part: PromptPart): this;
|
|
112
|
+
/**
|
|
113
|
+
* Build final prompt string (for simple generate)
|
|
114
|
+
*/
|
|
115
|
+
build(): string;
|
|
116
|
+
/**
|
|
117
|
+
* Build for chat completion (returns messages array)
|
|
118
|
+
*/
|
|
119
|
+
buildChat(): ChatMessage[];
|
|
120
|
+
/**
|
|
121
|
+
* Build as system + user prompt pair
|
|
122
|
+
*/
|
|
123
|
+
buildPair(): {
|
|
124
|
+
system: string;
|
|
125
|
+
user: string;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Reusable prompt template with variable interpolation
|
|
130
|
+
*/
|
|
131
|
+
export declare class PromptTemplate {
|
|
132
|
+
private template;
|
|
133
|
+
constructor(template: string);
|
|
134
|
+
/**
|
|
135
|
+
* Render template with variables
|
|
136
|
+
* Supports {{variable}} syntax
|
|
137
|
+
*/
|
|
138
|
+
render(vars: Record<string, unknown>): string;
|
|
139
|
+
/**
|
|
140
|
+
* Create template from string
|
|
141
|
+
*/
|
|
142
|
+
static from(template: string): PromptTemplate;
|
|
143
|
+
/**
|
|
144
|
+
* Create typed template with compile-time safety
|
|
145
|
+
*/
|
|
146
|
+
static typed<T extends Record<string, unknown>>(template: string): TypedPromptTemplate<T>;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Type-safe prompt template
|
|
150
|
+
*/
|
|
151
|
+
export declare class TypedPromptTemplate<T extends Record<string, unknown>> {
|
|
152
|
+
private template;
|
|
153
|
+
constructor(template: string);
|
|
154
|
+
render(vars: T): string;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Prompt strategies for different reasoning approaches
|
|
158
|
+
*/
|
|
159
|
+
export declare class PromptStrategy {
|
|
160
|
+
/**
|
|
161
|
+
* Zero-shot: direct instruction without examples
|
|
162
|
+
*/
|
|
163
|
+
static zeroShot(instruction: string): string;
|
|
164
|
+
/**
|
|
165
|
+
* Few-shot: instruction with examples
|
|
166
|
+
*/
|
|
167
|
+
static fewShot(instruction: string, examples: Array<{
|
|
168
|
+
input: string;
|
|
169
|
+
output: string;
|
|
170
|
+
}>): string;
|
|
171
|
+
/**
|
|
172
|
+
* Chain-of-thought: step-by-step reasoning
|
|
173
|
+
*/
|
|
174
|
+
static chainOfThought(question: string): string;
|
|
175
|
+
/**
|
|
176
|
+
* ReAct: Reasoning + Acting (for tool use)
|
|
177
|
+
*/
|
|
178
|
+
static reAct(task: string): string;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Chain prompts where output feeds into next input
|
|
182
|
+
*/
|
|
183
|
+
export declare class PromptChain {
|
|
184
|
+
private steps;
|
|
185
|
+
/**
|
|
186
|
+
* Add a step to the chain
|
|
187
|
+
*/
|
|
188
|
+
add(step: (input: string, client: any) => Promise<string>): this;
|
|
189
|
+
/**
|
|
190
|
+
* Execute the entire chain
|
|
191
|
+
*/
|
|
192
|
+
execute(initialInput: string, client: any): Promise<string[]>;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Pre-built prompt templates for common AI tasks
|
|
196
|
+
*/
|
|
197
|
+
export declare const PROMPTS: {
|
|
198
|
+
/**
|
|
199
|
+
* Generate a server name based on project context
|
|
200
|
+
*/
|
|
201
|
+
readonly generateServerName: (project?: string, description?: string) => string;
|
|
202
|
+
/**
|
|
203
|
+
* Suggest optimal server type based on workload
|
|
204
|
+
*/
|
|
205
|
+
readonly suggestServerType: (workload: string) => string;
|
|
206
|
+
/**
|
|
207
|
+
* Analyze resource usage and provide recommendations
|
|
208
|
+
*/
|
|
209
|
+
readonly analyzeResources: (cpu: number, memory: number, disk: number, activePorts?: string[]) => string;
|
|
210
|
+
/**
|
|
211
|
+
* Generate SSH troubleshooting tips
|
|
212
|
+
*/
|
|
213
|
+
readonly sshTroubleshoot: (error: string) => string;
|
|
214
|
+
/**
|
|
215
|
+
* Suggest server actions based on state
|
|
216
|
+
*/
|
|
217
|
+
readonly suggestActions: (status: string, age?: string) => string;
|
|
218
|
+
/**
|
|
219
|
+
* Generate a witty server status message
|
|
220
|
+
*/
|
|
221
|
+
readonly statusMessage: (status: string, name: string) => string;
|
|
222
|
+
};
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composable prompt architecture for scalable AI interactions
|
|
3
|
+
*
|
|
4
|
+
* Core concepts:
|
|
5
|
+
* - PromptPart: Composable building blocks
|
|
6
|
+
* - PromptBuilder: Fluent API for assembling prompts
|
|
7
|
+
* - PromptTemplate: Reusable templates with interpolation
|
|
8
|
+
* - PromptChain: Multi-step workflows
|
|
9
|
+
* - PromptStrategy: Different reasoning approaches
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* System instruction - sets AI role and behavior
|
|
13
|
+
*/
|
|
14
|
+
export class SystemInstruction {
|
|
15
|
+
role;
|
|
16
|
+
guidelines;
|
|
17
|
+
constructor(role, guidelines) {
|
|
18
|
+
this.role = role;
|
|
19
|
+
this.guidelines = guidelines;
|
|
20
|
+
}
|
|
21
|
+
toPrompt() {
|
|
22
|
+
const base = `You are a ${this.role}.`;
|
|
23
|
+
if (this.guidelines?.length) {
|
|
24
|
+
return `${base}\n\nGuidelines:\n${this.guidelines.map((g) => `- ${g}`).join("\n")}`;
|
|
25
|
+
}
|
|
26
|
+
return base;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Context - provides data/background information
|
|
31
|
+
*/
|
|
32
|
+
export class Context {
|
|
33
|
+
data;
|
|
34
|
+
constructor(data) {
|
|
35
|
+
this.data = data;
|
|
36
|
+
}
|
|
37
|
+
toPrompt() {
|
|
38
|
+
const entries = Object.entries(this.data)
|
|
39
|
+
.filter(([_, v]) => v !== undefined && v !== null && v !== "")
|
|
40
|
+
.map(([k, v]) => `- ${k}: ${typeof v === "object" ? JSON.stringify(v) : v}`)
|
|
41
|
+
.join("\n");
|
|
42
|
+
return entries ? `Context:\n${entries}` : "";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Examples - few-shot learning samples
|
|
47
|
+
*/
|
|
48
|
+
export class Examples {
|
|
49
|
+
examples;
|
|
50
|
+
constructor(examples) {
|
|
51
|
+
this.examples = examples;
|
|
52
|
+
}
|
|
53
|
+
toPrompt() {
|
|
54
|
+
if (this.examples.length === 0)
|
|
55
|
+
return "";
|
|
56
|
+
return this.examples
|
|
57
|
+
.map((ex, i) => `Example ${i + 1}:\nInput: ${ex.input}\nOutput: ${ex.output}`)
|
|
58
|
+
.join("\n\n");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Output format specification
|
|
63
|
+
*/
|
|
64
|
+
export class OutputFormat {
|
|
65
|
+
type;
|
|
66
|
+
schema;
|
|
67
|
+
constructor(type, schema) {
|
|
68
|
+
this.type = type;
|
|
69
|
+
this.schema = schema;
|
|
70
|
+
}
|
|
71
|
+
toPrompt() {
|
|
72
|
+
if (this.type === "json" && this.schema) {
|
|
73
|
+
return `Respond in JSON format with this schema:\n${JSON.stringify(this.schema, null, 2)}`;
|
|
74
|
+
}
|
|
75
|
+
return `Respond in ${this.type} format.`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Constraints - rules and limitations
|
|
80
|
+
*/
|
|
81
|
+
export class Constraints {
|
|
82
|
+
rules;
|
|
83
|
+
constructor(rules) {
|
|
84
|
+
this.rules = rules;
|
|
85
|
+
}
|
|
86
|
+
toPrompt() {
|
|
87
|
+
if (this.rules.length === 0)
|
|
88
|
+
return "";
|
|
89
|
+
return `Constraints:\n${this.rules.map((r) => `- ${r}`).join("\n")}`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Task - the main instruction/question
|
|
94
|
+
*/
|
|
95
|
+
export class Task {
|
|
96
|
+
instruction;
|
|
97
|
+
constructor(instruction) {
|
|
98
|
+
this.instruction = instruction;
|
|
99
|
+
}
|
|
100
|
+
toPrompt() {
|
|
101
|
+
return `Task:\n${this.instruction}`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Fluent builder for composable prompts
|
|
106
|
+
*/
|
|
107
|
+
export class PromptBuilder {
|
|
108
|
+
parts = [];
|
|
109
|
+
systemPart;
|
|
110
|
+
/**
|
|
111
|
+
* Set system role and guidelines
|
|
112
|
+
*/
|
|
113
|
+
system(role, guidelines) {
|
|
114
|
+
this.systemPart = new SystemInstruction(role, guidelines);
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Add context data
|
|
119
|
+
*/
|
|
120
|
+
context(data) {
|
|
121
|
+
this.parts.push(new Context(data));
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Add few-shot examples
|
|
126
|
+
*/
|
|
127
|
+
examples(examples) {
|
|
128
|
+
this.parts.push(new Examples(examples));
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Specify output format
|
|
133
|
+
*/
|
|
134
|
+
output(type, schema) {
|
|
135
|
+
this.parts.push(new OutputFormat(type, schema));
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Add constraints/rules
|
|
140
|
+
*/
|
|
141
|
+
constraints(...rules) {
|
|
142
|
+
this.parts.push(new Constraints(rules));
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Add the main task/instruction
|
|
147
|
+
*/
|
|
148
|
+
task(instruction) {
|
|
149
|
+
this.parts.push(new Task(instruction));
|
|
150
|
+
return this;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Add custom prompt part
|
|
154
|
+
*/
|
|
155
|
+
custom(part) {
|
|
156
|
+
this.parts.push(part);
|
|
157
|
+
return this;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Build final prompt string (for simple generate)
|
|
161
|
+
*/
|
|
162
|
+
build() {
|
|
163
|
+
const allParts = [
|
|
164
|
+
...(this.systemPart ? [this.systemPart] : []),
|
|
165
|
+
...this.parts,
|
|
166
|
+
];
|
|
167
|
+
return allParts
|
|
168
|
+
.map((p) => p.toPrompt())
|
|
169
|
+
.filter(Boolean)
|
|
170
|
+
.join("\n\n");
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Build for chat completion (returns messages array)
|
|
174
|
+
*/
|
|
175
|
+
buildChat() {
|
|
176
|
+
const messages = [];
|
|
177
|
+
if (this.systemPart) {
|
|
178
|
+
messages.push({ role: "system", content: this.systemPart.toPrompt() });
|
|
179
|
+
}
|
|
180
|
+
const userContent = this.parts
|
|
181
|
+
.map((p) => p.toPrompt())
|
|
182
|
+
.filter(Boolean)
|
|
183
|
+
.join("\n\n");
|
|
184
|
+
if (userContent) {
|
|
185
|
+
messages.push({ role: "user", content: userContent });
|
|
186
|
+
}
|
|
187
|
+
return messages;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Build as system + user prompt pair
|
|
191
|
+
*/
|
|
192
|
+
buildPair() {
|
|
193
|
+
return {
|
|
194
|
+
system: this.systemPart?.toPrompt() || "",
|
|
195
|
+
user: this.parts
|
|
196
|
+
.map((p) => p.toPrompt())
|
|
197
|
+
.filter(Boolean)
|
|
198
|
+
.join("\n\n"),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Reusable prompt template with variable interpolation
|
|
204
|
+
*/
|
|
205
|
+
export class PromptTemplate {
|
|
206
|
+
template;
|
|
207
|
+
constructor(template) {
|
|
208
|
+
this.template = template;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Render template with variables
|
|
212
|
+
* Supports {{variable}} syntax
|
|
213
|
+
*/
|
|
214
|
+
render(vars) {
|
|
215
|
+
let result = this.template;
|
|
216
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
217
|
+
const placeholder = `{{${key}}}`;
|
|
218
|
+
result = result.replaceAll(placeholder, String(value ?? ""));
|
|
219
|
+
}
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Create template from string
|
|
224
|
+
*/
|
|
225
|
+
static from(template) {
|
|
226
|
+
return new PromptTemplate(template);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Create typed template with compile-time safety
|
|
230
|
+
*/
|
|
231
|
+
static typed(template) {
|
|
232
|
+
return new TypedPromptTemplate(template);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Type-safe prompt template
|
|
237
|
+
*/
|
|
238
|
+
export class TypedPromptTemplate {
|
|
239
|
+
template;
|
|
240
|
+
constructor(template) {
|
|
241
|
+
this.template = template;
|
|
242
|
+
}
|
|
243
|
+
render(vars) {
|
|
244
|
+
return new PromptTemplate(this.template).render(vars);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Prompt strategies for different reasoning approaches
|
|
249
|
+
*/
|
|
250
|
+
export class PromptStrategy {
|
|
251
|
+
/**
|
|
252
|
+
* Zero-shot: direct instruction without examples
|
|
253
|
+
*/
|
|
254
|
+
static zeroShot(instruction) {
|
|
255
|
+
return instruction;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Few-shot: instruction with examples
|
|
259
|
+
*/
|
|
260
|
+
static fewShot(instruction, examples) {
|
|
261
|
+
return new PromptBuilder().examples(examples).task(instruction).build();
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Chain-of-thought: step-by-step reasoning
|
|
265
|
+
*/
|
|
266
|
+
static chainOfThought(question) {
|
|
267
|
+
return `${question}\n\nThink step by step. Show your work and reasoning process.`;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* ReAct: Reasoning + Acting (for tool use)
|
|
271
|
+
*/
|
|
272
|
+
static reAct(task) {
|
|
273
|
+
return `Task: ${task}
|
|
274
|
+
|
|
275
|
+
Think: [your reasoning about the current state]
|
|
276
|
+
Act: [action to take]
|
|
277
|
+
Observation: [result of action]
|
|
278
|
+
|
|
279
|
+
Repeat Think/Act/Observation until the task is complete.`;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Chain prompts where output feeds into next input
|
|
284
|
+
*/
|
|
285
|
+
export class PromptChain {
|
|
286
|
+
steps = [];
|
|
287
|
+
/**
|
|
288
|
+
* Add a step to the chain
|
|
289
|
+
*/
|
|
290
|
+
add(step) {
|
|
291
|
+
this.steps.push(step);
|
|
292
|
+
return this;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Execute the entire chain
|
|
296
|
+
*/
|
|
297
|
+
async execute(initialInput, client) {
|
|
298
|
+
const results = [];
|
|
299
|
+
let current = initialInput;
|
|
300
|
+
for (const step of this.steps) {
|
|
301
|
+
current = await step(current, client);
|
|
302
|
+
results.push(current);
|
|
303
|
+
}
|
|
304
|
+
return results;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// ============================================================================
|
|
308
|
+
// PRE-BUILT PROMPTS (Refactored using composable architecture)
|
|
309
|
+
// ============================================================================
|
|
310
|
+
/**
|
|
311
|
+
* Pre-built prompt templates for common AI tasks
|
|
312
|
+
*/
|
|
313
|
+
export const PROMPTS = {
|
|
314
|
+
/**
|
|
315
|
+
* Generate a server name based on project context
|
|
316
|
+
*/
|
|
317
|
+
generateServerName: (project, description) => {
|
|
318
|
+
return new PromptBuilder()
|
|
319
|
+
.system("server naming specialist", [
|
|
320
|
+
"Create memorable, technical names",
|
|
321
|
+
"Use lowercase letters and hyphens only",
|
|
322
|
+
])
|
|
323
|
+
.context({ project, description })
|
|
324
|
+
.constraints("8-15 characters maximum", "lowercase letters only", "hyphens allowed but no consecutive hyphens", "Return ONLY the name, no explanation")
|
|
325
|
+
.task("Generate a short, memorable server name.")
|
|
326
|
+
.build();
|
|
327
|
+
},
|
|
328
|
+
/**
|
|
329
|
+
* Suggest optimal server type based on workload
|
|
330
|
+
*/
|
|
331
|
+
suggestServerType: (workload) => {
|
|
332
|
+
return new PromptBuilder()
|
|
333
|
+
.system("Hetzner cloud infrastructure expert", [
|
|
334
|
+
"Know all Hetzner server types and their capabilities",
|
|
335
|
+
"Consider cost-effectiveness",
|
|
336
|
+
])
|
|
337
|
+
.context({ workload })
|
|
338
|
+
.examples([
|
|
339
|
+
{
|
|
340
|
+
input: "High-traffic web server with moderate CPU needs",
|
|
341
|
+
output: "cpx21 - Good balance of performance and cost for web workloads",
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
input: "Development/testing server",
|
|
345
|
+
output: "cpx11 - Lowest cost option, sufficient for development",
|
|
346
|
+
},
|
|
347
|
+
])
|
|
348
|
+
.constraints("Respond with just the server type name", "Follow with one brief sentence explaining why", "Suggest any appropriate Hetzner server type based on the workload needs")
|
|
349
|
+
.task("Suggest the best Hetzner server type for this workload.")
|
|
350
|
+
.build();
|
|
351
|
+
},
|
|
352
|
+
/**
|
|
353
|
+
* Analyze resource usage and provide recommendations
|
|
354
|
+
*/
|
|
355
|
+
analyzeResources: (cpu, memory, disk, activePorts) => {
|
|
356
|
+
const contextData = {
|
|
357
|
+
cpu: `${cpu}%`,
|
|
358
|
+
memory: `${memory}%`,
|
|
359
|
+
disk: `${disk}%`,
|
|
360
|
+
};
|
|
361
|
+
if (activePorts && activePorts.length > 0) {
|
|
362
|
+
contextData.activePorts =
|
|
363
|
+
activePorts.slice(0, 10).join(", ") +
|
|
364
|
+
(activePorts.length > 10 ? ` (+${activePorts.length - 10} more)` : "");
|
|
365
|
+
}
|
|
366
|
+
return new PromptBuilder()
|
|
367
|
+
.system("DevOps monitoring specialist", [
|
|
368
|
+
"Assess server health holistically",
|
|
369
|
+
"Prioritize actionable advice",
|
|
370
|
+
])
|
|
371
|
+
.context(contextData)
|
|
372
|
+
.examples([
|
|
373
|
+
{
|
|
374
|
+
input: "CPU: 95%, Memory: 90%, Disk: 50%",
|
|
375
|
+
output: "CRITICAL: Immediate scale-up required. CPU and memory are at dangerous levels.",
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
input: "CPU: 15%, Memory: 25%, Disk: 30%",
|
|
379
|
+
output: "HEALTHY: All metrics within normal range. No action needed.",
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
input: "CPU: 45%, Memory: 85%, Disk: 20%",
|
|
383
|
+
output: "WARNING: Memory usage high. Consider optimizing applications or upgrading memory.",
|
|
384
|
+
},
|
|
385
|
+
])
|
|
386
|
+
.constraints("Assessment must be one of: HEALTHY, WARNING, CRITICAL", "Provide exactly one sentence for assessment", "Provide exactly one actionable recommendation if not HEALTHY", "Keep total response under 100 words")
|
|
387
|
+
.task("Analyze the server resource usage and provide health assessment.")
|
|
388
|
+
.build();
|
|
389
|
+
},
|
|
390
|
+
/**
|
|
391
|
+
* Generate SSH troubleshooting tips
|
|
392
|
+
*/
|
|
393
|
+
sshTroubleshoot: (error) => {
|
|
394
|
+
return new PromptBuilder()
|
|
395
|
+
.system("SSH troubleshooting expert", [
|
|
396
|
+
"Know common SSH issues and solutions",
|
|
397
|
+
"Provide practical, step-by-step solutions",
|
|
398
|
+
])
|
|
399
|
+
.context({ error })
|
|
400
|
+
.examples([
|
|
401
|
+
{
|
|
402
|
+
input: "Connection refused",
|
|
403
|
+
output: "1. Verify SSH service is running: systemctl status sshd\n2. Check firewall rules\n3. Confirm correct port (usually 22)",
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
input: "Permission denied (publickey)",
|
|
407
|
+
output: "1. Verify public key is added to server's ~/.ssh/authorized_keys\n2. Check file permissions: chmod 700 ~/.ssh and chmod 600 ~/.ssh/authorized_keys\n3. Ensure you're using the correct private key",
|
|
408
|
+
},
|
|
409
|
+
])
|
|
410
|
+
.constraints("Provide 2-3 specific troubleshooting steps", "Each step should be actionable", "Keep responses concise")
|
|
411
|
+
.task("Provide SSH troubleshooting steps for this error.")
|
|
412
|
+
.build();
|
|
413
|
+
},
|
|
414
|
+
/**
|
|
415
|
+
* Suggest server actions based on state
|
|
416
|
+
*/
|
|
417
|
+
suggestActions: (status, age) => {
|
|
418
|
+
return new PromptBuilder()
|
|
419
|
+
.system("Server operations specialist", [
|
|
420
|
+
"Understand server lifecycle management",
|
|
421
|
+
"Consider cost implications",
|
|
422
|
+
])
|
|
423
|
+
.context({ status, age })
|
|
424
|
+
.examples([
|
|
425
|
+
{
|
|
426
|
+
input: "Status: stopped, Age: 2 hours",
|
|
427
|
+
output: "Actions: start (to resume service), delete (if no longer needed)",
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
input: "Status: running, Age: 30 days",
|
|
431
|
+
output: "Actions: reboot (for maintenance), resize (if performance issues)",
|
|
432
|
+
},
|
|
433
|
+
])
|
|
434
|
+
.constraints("Suggest 1-2 appropriate actions", "Include very brief explanation for each", "Consider actions: start, stop, restart, delete, resize")
|
|
435
|
+
.task("Suggest appropriate server management actions.")
|
|
436
|
+
.build();
|
|
437
|
+
},
|
|
438
|
+
/**
|
|
439
|
+
* Generate a witty server status message
|
|
440
|
+
*/
|
|
441
|
+
statusMessage: (status, name) => {
|
|
442
|
+
return new PromptBuilder()
|
|
443
|
+
.system("Playful status message generator", [
|
|
444
|
+
"Be lighthearted but professional",
|
|
445
|
+
"Use puns and wordplay when appropriate",
|
|
446
|
+
])
|
|
447
|
+
.context({ status, name })
|
|
448
|
+
.examples([
|
|
449
|
+
{
|
|
450
|
+
input: "Status: running, Name: prod-db-01",
|
|
451
|
+
output: "🟢 prod-db-01 is alive and kicking!",
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
input: "Status: stopped, Name: dev-server",
|
|
455
|
+
output: "💤 dev-server is taking a nap",
|
|
456
|
+
},
|
|
457
|
+
])
|
|
458
|
+
.constraints("Keep under 50 characters", "Use appropriate emoji for status", "Be creative and memorable")
|
|
459
|
+
.task("Generate a brief, witty status message.")
|
|
460
|
+
.build();
|
|
461
|
+
},
|
|
462
|
+
};
|