@eng-ai/sdk
v2.9.2
Published
Official JavaScript SDK for ENG-AI External API v2
Readme
@eng-ai/sdk
Official JavaScript SDK for ENG-AI External API v2.
Install
npm install @eng-ai/sdkUsage
import { EngAIClient, EngAIError } from "@eng-ai/sdk";
const client = new EngAIClient(
process.env.ENG_AI_API_KEY,
"https://your-domain/api/v2",
{
debug: false, // set true only in trusted environments
timeoutMs: 60000
}
);
const agentMode = (process.env.ENG_AI_AGENT_MODE || "autonomous").toLowerCase();
const specialistAgentId = process.env.ENG_AI_AGENT_ID || "general";
const payload = {
message: "Explique o conceito de talude",
normativeMode: true,
normId: "auto"
};
const response =
agentMode === "specialist"
? await client.invokeAgent(specialistAgentId, payload)
: await client.invokeAgent(payload);
console.log(response.result.content);
console.log(response.normative?.citations ?? []);
console.log(response.request.session_id);
// Recommended error handling
try {
await client.invokeAgent(payload);
} catch (error) {
if (error instanceof EngAIError) {
console.error("ENG-AI request failed", {
status: error.status,
code: error.code,
detail: error.detail,
requestId: error.requestId,
retryAfter: error.retryAfter
});
} else {
console.error("Unexpected error", error);
}
}Agent mode options:
ENG_AI_AGENT_MODE=autonomous: omiteagent_ide deixa o Core Orchestrator escolher.ENG_AI_AGENT_MODE=specialist: fixaagent_idviaENG_AI_AGENT_ID(ex.:general,contract_managerou aliasproject_manager).
Project creation (API key only):
const project = await client.createProject({
name: "Projeto Piloto",
description: "Projeto criado via SDK CLI",
projectLocation: "São Paulo - SP"
});
const projects = await client.listProjects({ limit: 10, offset: 0 });
console.log(project.id, projects.length);SDK conversation history:
const first = await client.invokeAgent({
message: "Explique o conceito de talude",
});
const sessionId = first.request.session_id;
const second = await client.invokeAgent({
sessionId,
message: "Continue e detalhe os tipos de contenção",
});
const sessions = await client.listSdkSessions({ limit: 10 });
const session = await client.getSdkSession(sessionId);
console.log(second.request.session_id);
console.log(sessions.map((item) => item.id));
console.log(session.messages.length);Desktop LAN authorization (metadata-only):
const proof = await client.createDesktopLanAuthorization({
serverInstanceId: "stable-non-secret-server-id"
});The proof is short-lived and audience-bound. It contains identity and the relevant Desktop permissions only. Agent definitions, system prompts, tools, documents, local chat and BYOK credentials are never included and remain under customer custody on the Desktop LAN server.
Desktop private local-context invocation:
const capabilities = await client.getCapabilities();
if (!capabilities.no_persistence || capabilities.desktop_contract_version < 1) {
throw new Error("ENG-AI Cloud does not support the Desktop privacy contract");
}
const response = await client.invokeAgent("contract_manager", {
message: "Analise os trechos locais e crie a tarefa de revisão",
desktopContractVersion: 1,
projectId: "project-id",
clientContext: {
digest: "sha256-local-context",
chunks: [
{
document_id: "local-doc-id",
chunk_index: 0,
text: "Trecho bounded do índice local",
score: 0.91
}
]
},
chatHistory: [{ role: "user", content: "Histórico local bounded" }],
privacy: { mode: "no_persistence", allow_project_mutations: true },
idempotencyKey: "desktop-project-mutation-uuid"
});
console.log(response.privacy.persisted); // falseTask autonomy mode by project:
await client.setProjectAutonomyMode(project.id, "approval_required");
const context = await client.getProjectContext(project.id);
console.log(context.autonomous_tasks_mode);Project intake (initial_full and delta_refresh):
const intakeStatus = await client.getProjectIntakeStatus(project.id);
if (intakeStatus.intake_status === "ready") {
await client.runProjectIntake(project.id, { mode: "delta_refresh" });
} else {
await client.runProjectIntake(project.id, { mode: "initial_full" });
}Project knowledge (status, lint issues, manual rebuild):
const knowledgeStatus = await client.getProjectKnowledgeStatus(project.id);
const knowledgePages = await client.listProjectKnowledgePages(project.id, {
limit: 20,
includeGraph: true,
});
const knowledgeIssues = await client.listProjectKnowledgeIssues(project.id, {
onlyOpen: true,
limit: 10
});
await client.rebuildProjectKnowledge(project.id, {
idempotencyKey: `knowledge-rebuild-${project.id}`
});
const pagesCount = Array.isArray(knowledgePages)
? knowledgePages.length
: (knowledgePages?.pages || []).length;
const graphNodes = Array.isArray(knowledgePages)
? 0
: (knowledgePages?.graph?.nodes || []).length;
console.log(knowledgeStatus.status, pagesCount, knowledgeIssues.length, graphNodes);Project chat suggestion confirmation (when response includes context_update_suggestion):
const response = await client.invokeAgent({
message: "A ART e licenças foram entregues, estamos em dia agora.",
projectId: project.id,
});
const suggestion = response?.context_update_suggestion;
if (suggestion) {
await client.confirmProjectContextSuggestion(project.id, suggestion.suggestion_id, {
summary: suggestion.summary,
proposedPatch: suggestion.proposed_patch,
expiresAt: suggestion.expires_at,
checksum: suggestion.checksum,
});
}Project documents (tags, filters, upload, update):
const uploaded = await client.uploadDocument({
file: new Blob(["conteudo tecnico"], { type: "text/plain" }),
fileName: "escopo.txt",
projectId: project.id,
tags: ["Marco Estrutural", "Planejamento"]
});
await client.updateDocumentTags(uploaded.id, ["Marco Estrutural", "Revisado"]);
const docsAny = await client.listDocuments({
projectId: project.id,
tags: ["Marco Estrutural", "Revisado"],
tagMode: "any"
});
const docsAll = await client.listDocuments({
projectId: project.id,
tags: ["Marco Estrutural", "Revisado"],
tagMode: "all"
});
console.log(docsAny.length, docsAll.length);External approval flow (pull):
const actionable = await client.listActionableAutomationPlans(30);
const pending = actionable.find((plan) => plan.status === "pending_approval");
if (pending) {
await client.approveAutomationPlan(pending.project_id, pending.id, "Approved by integration bot");
await client.applyAutomationPlan(pending.project_id, pending.id);
}Supported automation plan actions:
listActionableAutomationPlans(limit?)listProjectAutomationPlans(projectId, { status? })approveAutomationPlan(projectId, planId, note?, { idempotencyKey? })rejectAutomationPlan(projectId, planId, note?, { idempotencyKey? })applyAutomationPlan(projectId, planId, { idempotencyKey? })
Supported SDK history actions:
listSdkSessions({ limit?, offset?, projectId? })getSdkSession(sessionId)
Supported project knowledge actions:
getProjectIntakeStatus(projectId)runProjectIntake(projectId, { mode? })getProjectKnowledgeStatus(projectId)listProjectKnowledgePages(projectId, { limit?, includeGraph? })listProjectKnowledgeIssues(projectId, { onlyOpen?, limit? })rebuildProjectKnowledge(projectId, { idempotencyKey? })confirmProjectContextSuggestion(projectId, suggestionId, { summary, proposedPatch, expiresAt, checksum })
External user settings (API key owner scope):
const ai = await client.getAISettings();
await client.setAISettings({
provider: "vertex",
model: "gemini-2.5-flash",
projectModel: "gemini-2.5-flash",
vertexProjectId: "my-gcp-project",
vertexLocation: "southamerica-east1",
vertexServiceAccountJson: process.env.VERTEX_SERVICE_ACCOUNT_JSON,
preferredTimezone: "America/Sao_Paulo",
});
await client.setVoiceLiveEnabled(true);
const general = await client.getGeneralSettings();
await client.setGeneralSettings(general.preferred_timezone || "America/Sao_Paulo");External profile (API key owner scope):
const profile = await client.getProfile();
await client.updateProfile({
preferredName: "Felipe",
honorific: "Eng.",
crea: "123456/D",
specialty: "Geotecnia",
});CLI (eng-ai) included in package:
ENG_AI_API_KEY=sk_xxx eng-ai sdk sessions list --limit 10
ENG_AI_API_KEY=sk_xxx eng-ai sdk sessions get --session-id <id>
ENG_AI_API_KEY=sk_xxx eng-ai projects autonomy set --project-id <id> --mode approval_required
ENG_AI_API_KEY=sk_xxx eng-ai plans actionable list --limit 30
ENG_AI_API_KEY=sk_xxx eng-ai plans approve --project-id <id> --plan-id <id> --note "Approved"
ENG_AI_API_KEY=sk_xxx eng-ai plans apply --project-id <id> --plan-id <id>
ENG_AI_API_KEY=sk_xxx eng-ai plans watch --interval 15 --limit 30
ENG_AI_API_KEY=sk_xxx eng-ai settings ai get
ENG_AI_API_KEY=sk_xxx eng-ai settings ai set --provider google --model gemini-3.1-flash-lite-preview --preferred-timezone America/Sao_Paulo
ENG_AI_API_KEY=sk_xxx eng-ai settings ai set --provider vertex --model gemini-2.5-flash --vertex-project-id my-gcp-project --vertex-location southamerica-east1 --vertex-service-account-json "$VERTEX_SERVICE_ACCOUNT_JSON"
ENG_AI_API_KEY=sk_xxx eng-ai settings ai voice-live --enabled true
ENG_AI_API_KEY=sk_xxx eng-ai settings general set --preferred-timezone America/Sao_Paulo
ENG_AI_API_KEY=sk_xxx eng-ai profile get
ENG_AI_API_KEY=sk_xxx eng-ai profile set --preferred-name Felipe --honorific "Eng." --crea "123456/D" --specialty GeotecniaDefault base URL: https://api.eng-ai.com/api/v2.
Security Notes
- Use your ENG-AI API key only in trusted server environments.
- Do not ship secrets in frontend bundles.
- Keep idempotency enabled for mutation-heavy integrations.
- Keep
debugdisabled in production logs unless strictly needed.
License
MIT
