@teo_dev/keen-sdk-types
v1.0.11
Published
Unified type definitions for Keen Engine SDK modules
Readme
@teo_dev/keen-sdk-types
Unified TypeScript type definitions for all Keen Engine SDK modules.
Installation
npm install @teo_dev/keen-sdk-typesIncluded SDKs
| Module | Type File | Description |
|---|---|---|
| system/files | SDK_Files.d.ts | File management, processing, and factory |
| system/chat | SDK_Chat.d.ts | Real-time chat output and sub-agent streaming |
| system/log | SDK_Logs.d.ts | Logging (error, warning, info, debug) |
| system/flow | SDK_Flow.d.ts | Flow pipeline execution |
| system/agent | SDK_Agent.d.ts | Agent response history and prompt injection |
| system/session | SDK_Session.d.ts | Session key/value storage |
| system/tools | SDK_Tools.d.ts | Utility helpers like UUIDs and timestamps |
| system/database | SDK_Database.d.ts | Database operations (sessions, agents, messages) |
Usage
Once installed, import directly from the system modules inside your sandbox:
Files
The Files SDK exposes three entry points:
FilesManager— upload, search, get/update/delete file recordsFilesProcessor— format-specific operations (pdf.*,excel.*,word.*,text.*)FilesFactory— wrap rawFileDatainto typed file instances (FilePDF,FileMSExcel,FileMSWord, ...)
Most operations are also available directly on file instances (e.g. file.styleRange(...)).
Upload, search, copy, delete
import { FilesManager, FilesProcessor } from 'system/files';
// Upload from a Buffer (Node) — `expiresIn` removes the file after the duration
const file = await FilesManager.uploadBuffer(buffer, 'report.pdf', {
expiresIn: { minutes: 30 }
});
// Or from base64
const fromBase64 = await FilesManager.createFromBase64({
originalName: 'notes.txt',
data: 'SGVsbG8sIHRoaXMgaXMgbXkgZmlsZQ==',
});
// Lookup by id, search, copy, delete
const fetched = await FilesManager.getFileById(file.data.id);
const matches = await FilesManager.searchFiles({ mimeType: 'application/pdf' });
const copy = await fetched.copy({ expiresIn: { minutes: 5 } });
await copy.delete();Wrap raw FileData with FilesFactory
When you already have a raw FileData record (from getFileByIdRaw, a search result, or persisted state) and want a typed instance with operation methods, use FilesFactory.create. The correct subclass is chosen automatically from the MIME type.
import { FilesManager, FilesFactory, FileMSExcel } from 'system/files';
// Pull the plain record (no methods, just data)
const raw = await FilesManager.getFileByIdRaw('616372e7-dcfe-4b56-9acb-b8036d684389');
// Wrap it into a typed file instance
const file = FilesFactory.create(raw);
// Narrow + use Excel-specific operations
if (file instanceof FileMSExcel) {
const range = await file.readRange({ sheet: 'Sheet1', range: 'A1:C10' });
await file.styleRange({
sheet: 'Sheet1',
range: 'A1:C1',
style: { font: { bold: true }, border: { bottom: { style: 'thin' } } },
});
}const pdf = await FilesManager.getFileById('f7730e41-1aa7-4f50-8d71-a603d87ea0f5');
// Read
const info = await pdf.getInfo(); // page count, metadata, bookmarks
const text = await pdf.getText({ pages: [1, 2, 3] }); // extract specific pages
// Create new files
const pages = await pdf.extractPages({ pageRanges: [{ startPage: 1, endPage: 10 }] });
const images = await pdf.extractImages({ format: 'jpeg' });
const rendered = await pdf.pagesToImages({ format: 'jpeg' });
// Update in place
await pdf.addPageNumbers({ startAt: 1, format: 'Page {page} of {total}', fontSize: 11 });
await pdf.compress({ imageDpi: 72 });
// Async variant for long-running ops — returns a processing id to poll
const job = await pdf.extractPagesAsync({}, { expiresIn: { minutes: 5 } });
const status = await FilesProcessor.getFPOperation(job.fileProcessingId);Excel
// Create a workbook with named sheets
const wb = await FilesProcessor.excel.createWorkbook(
{ name: 'Report', sheets: ['Summary', 'Data'] },
{ expiresIn: { minutes: 30 } }
);
// Read / write
const range = await wb.readRange({ sheet: 'Summary', range: 'A1:C10' });
const cell = await wb.readCell({ sheet: 'Summary', cell: 'B2' });
await wb.updateRange({
sheet: 'Summary',
range: 'A1:C2',
values: [['Header A', 'Header B', 'Header C'], [1, 2, 3]],
});
await wb.updateCell({ sheet: 'Summary', cell: 'D2', value: 'note' });
// Sheet management
await wb.addSheet({ name: 'Notes' });
await wb.copySheet({ sheet: 'Summary', name: 'Summary_Backup' });
await wb.deleteSheet({ sheet: 'Notes' });
// Row / column manipulation
await wb.insertRow({ sheet: 'Summary', row: 3, count: 2 });
await wb.deleteRow({ sheet: 'Summary', row: 5 });
await wb.insertColumn({ sheet: 'Summary', column: 'B' });
await wb.deleteColumn({ sheet: 'Summary', column: 'D' });
// Style cells — font, fill, alignment, number format, borders, protection.
// Properties merge with existing styles; only what you pass is changed.
await wb.styleRange({
sheet: 'Summary',
range: 'A1:C1',
style: {
font: { bold: true, color: '#FFFFFF', size: 14 },
fill: { color: '#003366' }, // pattern defaults to solid
alignment: { horizontal: 'center', vertical: 'center' },
border: { bottom: { style: 'medium', color: '#000000' } },
numberFormat: '0.00',
},
});
// Merge / unmerge cells. Only the top-left value/format survives a merge.
// Unmerge fails if the range doesn't match an existing merge exactly.
await wb.mergeCells({ sheet: 'Summary', range: 'A1:C1' });
await wb.unmergeCells({ sheet: 'Summary', range: 'A1:C1' });
// Workbook info
const meta = await wb.getInfo(); // sheets, dimensions, named ranges, document propertiesWord
// Create a document, optionally pre-seeded with paragraphs
const doc = await FilesProcessor.word.createDocument(
{ name: 'agreement', paragraphs: ['First paragraph.', 'Second paragraph.'] },
{ expiresIn: { minutes: 30 } }
);
// Read
const text = await doc.getText({ header: true, footer: true });
const info = await doc.getInfo(); // word/paragraph/table counts, headings, hasMacros, etc.
// Replace literal text across body, tables, headers and footers
await doc.replaceText({ find: 'TODO', replace: 'Done', caseSensitive: true });
// Export to PDF — returns a new FilePDF
const pdf = await doc.exportToPdf({ name: 'agreement.pdf' });
// Render a template with variables. Templates support a full template language
// (see the wordRenderTemplateParams JSDoc for the complete syntax reference):
//
// • Inline: {{ user.name }}, {{ items|length }}
// • Conditional: {%if isActive %} ... {% endif %} (or {%p if %} for paragraph removal)
// • Loops: {%p for item in items %} ... {%p endfor %}
// • Table rows: {%tr for row in rows %} ... {%tr endfor %}
// • Filters: {{ value | upper }}, comparisons, expressions
const filled = await doc.renderTemplate({
name: 'invoice-2026-04',
variables: {
clientName: 'Acme Corp',
showSection: true,
rows: [
{ num: 1, item: 'Consulting', amount: 1200 },
{ num: 2, item: 'Hosting', amount: 300 },
],
},
});Text
// Create a plain text file (defaults to "text.txt" if no name given)
const note = await FilesProcessor.text.createTextFile(
{ name: 'notes', content: 'First line.\n' },
{ expiresIn: { minutes: 30 } }
);
// Read
const info = await note.getInfo(); // { lines, chars, bytes, words }
const content = await note.getContent(); // full UTF-8 string
// Update — full replacement
await note.updateContent({ content: 'Replaced content.\n' });
// Append — no automatic newline is inserted between old and new content
await note.appendContent({ content: 'Second line.\n' });
// Replace literal text (all occurrences, no regex)
await note.replaceText({ find: 'Second', replace: 'Last', caseSensitive: true });Chat
import Chat from 'system/chat';
Chat.writeOut('Hello from the agent!');
Chat.writeThinking('Processing your request...');
Chat.writeError('Something went wrong');
// Sub-agent streaming
Chat.writeAgentStart(mainSessionId, subSessionId, 'DataAgent');
Chat.writeAgentStream(subSessionId, 'partial response...');
Chat.writeAgentEnd(subSessionId, 'completed');
Chat.writeFiles([{ id: 'file-1', originalName: 'report.pdf', mimeType: 'application/pdf', size: 1024 }]);Log
import Log from 'system/log';
Log.info('Processing started');
Log.warning('Rate limit approaching');
Log.error('Connection failed');
Log.debug('Payload received: ...');Flow
import Flow from 'system/flow';
const result = await Flow.run('Main-Start', { key: 'value' });
if ('error' in result) {
Chat.writeError(result.message);
} else {
Chat.writeOut(JSON.stringify(result)); // dictionary returned from pipeline
}Agent
import Agent from 'system/agent';
const lastResponse = Agent.getAgentLastResponse('WriterAgent');
const promptResult = Agent.setAgentPrompt('WriterAgent', {
sessionID: 'session-123',
prompt: 'Summarize the uploaded files.',
role: 'user'
});
if (promptResult?.error) {
Chat.writeError(promptResult.message);
}Session
import Session from 'system/session';
// Built-in keys available by default: "sessionID", "email", "userID", "requestID"
const sessionId = Session.getSessionValue('sessionID');
const email = Session.getSessionValue('email');
const userId = Session.getSessionValue('userID');
const requestId = Session.getSessionValue('requestID');
// You can also store and retrieve custom values
Session.setSessionValue('draftMode', true);
if (Session.hasSessionKey('draftMode')) {
Chat.writeOut(JSON.stringify(Session.getSessionValue('draftMode')));
}
Chat.writeOut(JSON.stringify(Session.getSessionSize()));Database
import Database from 'system/database';
import Chat from 'system/chat';
import Session from 'system/session';
const sessionId = Session.getSessionValue('sessionID') as string;
// Session
let session = await Database.Session.get(sessionId);
if (!session) {
session = await Database.Session.create({ sessionId });
Chat.writeOut('Session created.');
}
Chat.writeOut(JSON.stringify(session));
// Agent
// We can extract the actual agent/nodeId from this response
const agents = await Database.Agent.getBySession(sessionId);
const nodeId = agents[0]?.nodeId;
Chat.writeOut(JSON.stringify(agents));
// Message
const created = await Database.Message.create({
sessionId,
nodeId,
role: 'user',
content: 'Summarize the project status.',
systemCall: 0,
systemResponse: 0,
prePrompt: 0,
skipOtherReason: 0,
filePaths: [{ path: '/tmp/report.pdf' }],
specialRules: [{ type: 'custom', results: 'Return 3 bullets only.' }]
});
const messages = await Database.Message.get(sessionId, nodeId);
Chat.writeOut(JSON.stringify(messages));
const updated = await Database.Message.update(created.id, {
content: 'Summarize in valid JSON.',
specialRules: [{ type: 'custom', results: 'Output must be JSON.' }]
});
Chat.writeOut(JSON.stringify(updated));Tools
import Tools from 'system/tools';
const requestId = Tools.generateUUID();
const startedAt = Tools.getTimestamp();Project Structure
keen-sdk-types/
├── package.json
├── index.d.ts <- references all SDK type files
└── types/
├── SDK_Files.d.ts <- system/files
├── SDK_Chat.d.ts <- system/chat
├── SDK_Logs.d.ts <- system/log
├── SDK_Flow.d.ts <- system/flow
├── SDK_Agent.d.ts <- system/agent
├── SDK_Session.d.ts <- system/session
├── SDK_Tools.d.ts <- system/tools
└── SDK_Database.d.ts <- system/databaseAdding a New SDK
- Create a new type file in
types/(e.g.SDK_Storage.d.ts) - Add a
/// <reference path="./types/SDK_Storage.d.ts" />line inindex.d.ts - Bump the version and publish
Publishing
npm login
npm publish --access public