iranti 0.2.24 → 0.2.25
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.
|
@@ -3824,6 +3824,18 @@ async function setupCommand(args) {
|
|
|
3824
3824
|
let result = null;
|
|
3825
3825
|
await withPromptSession(async (prompt) => {
|
|
3826
3826
|
let setupMode = 'isolated';
|
|
3827
|
+
printChoiceGuide('Runtime Mode Choices', [
|
|
3828
|
+
{
|
|
3829
|
+
choice: 'isolated',
|
|
3830
|
+
meaning: 'one project gets its own runtime root and usually its own instance boundary',
|
|
3831
|
+
useWhen: 'one repo should stay self-contained and you do not want other repos sharing its memory/runtime by default.',
|
|
3832
|
+
},
|
|
3833
|
+
{
|
|
3834
|
+
choice: 'shared',
|
|
3835
|
+
meaning: 'multiple projects can bind to the same runtime root and instances under it',
|
|
3836
|
+
useWhen: 'several repos should intentionally share one Iranti instance and memory space.',
|
|
3837
|
+
},
|
|
3838
|
+
]);
|
|
3827
3839
|
while (true) {
|
|
3828
3840
|
const chosen = (await prompt.line('Runtime mode (isolated or shared)', 'isolated') ?? 'isolated').trim().toLowerCase();
|
|
3829
3841
|
if (chosen === 'shared' || chosen === 'isolated') {
|
|
@@ -3835,10 +3847,20 @@ async function setupCommand(args) {
|
|
|
3835
3847
|
let finalScope = 'user';
|
|
3836
3848
|
let finalRoot = '';
|
|
3837
3849
|
if (setupMode === 'isolated') {
|
|
3850
|
+
printWizardNotes('Isolated Runtime Path', [
|
|
3851
|
+
'This folder becomes the runtime root for this isolated setup.',
|
|
3852
|
+
'Iranti stores instance env files, runtime metadata, logs, and install metadata under this root.',
|
|
3853
|
+
'Use a project-local path like `<repo>/.iranti-runtime` when one repo should own its own runtime.',
|
|
3854
|
+
]);
|
|
3838
3855
|
finalRoot = path_1.default.resolve(await promptNonEmpty(prompt, 'Isolated runtime path', explicitRoot ?? path_1.default.join(process.cwd(), '.iranti-runtime')));
|
|
3839
3856
|
finalScope = 'user';
|
|
3840
3857
|
}
|
|
3841
3858
|
else {
|
|
3859
|
+
printWizardNotes('Shared Runtime Scope', [
|
|
3860
|
+
'Shared mode uses one runtime root that can hold multiple named instances.',
|
|
3861
|
+
'Choose `user` for a per-user machine install. Choose `system` only when you deliberately want a machine-wide shared location.',
|
|
3862
|
+
'Use `--root` instead when you need an exact custom shared runtime path.',
|
|
3863
|
+
]);
|
|
3842
3864
|
while (true) {
|
|
3843
3865
|
const chosenScope = (await prompt.line('Install scope (user or system)', explicitScope ?? 'user') ?? 'user').trim().toLowerCase();
|
|
3844
3866
|
if (chosenScope === 'user' || chosenScope === 'system') {
|
|
@@ -3875,6 +3897,23 @@ async function setupCommand(args) {
|
|
|
3875
3897
|
let databaseProvisioned = false;
|
|
3876
3898
|
let dockerContainerName;
|
|
3877
3899
|
let databaseMode = recommendedDatabaseMode;
|
|
3900
|
+
printChoiceGuide('Database Mode Choices', [
|
|
3901
|
+
{
|
|
3902
|
+
choice: 'local',
|
|
3903
|
+
meaning: 'use PostgreSQL already running on this machine',
|
|
3904
|
+
useWhen: 'you already have local Postgres with pgvector, or want Iranti to reuse a local developer database.',
|
|
3905
|
+
},
|
|
3906
|
+
{
|
|
3907
|
+
choice: 'docker',
|
|
3908
|
+
meaning: 'start or reuse a local PostgreSQL container just for the database',
|
|
3909
|
+
useWhen: 'you want a reliable local pgvector path without managing a direct host Postgres install.',
|
|
3910
|
+
},
|
|
3911
|
+
{
|
|
3912
|
+
choice: 'managed',
|
|
3913
|
+
meaning: 'use a remote PostgreSQL connection string you already control',
|
|
3914
|
+
useWhen: 'your database lives on Railway, Supabase, Neon, or another hosted PostgreSQL service.',
|
|
3915
|
+
},
|
|
3916
|
+
]);
|
|
3878
3917
|
while (true) {
|
|
3879
3918
|
const defaultMode = recommendedDatabaseMode;
|
|
3880
3919
|
const dbMode = (await prompt.line('Database mode (local, managed, or docker)', defaultMode) ?? defaultMode).trim().toLowerCase();
|
|
@@ -3929,6 +3968,23 @@ async function setupCommand(args) {
|
|
|
3929
3968
|
console.log(`${warnLabel()} Choose one of: local, managed, docker.`);
|
|
3930
3969
|
}
|
|
3931
3970
|
let provider = normalizeProvider(existingInstance?.env.LLM_PROVIDER ?? 'openai') ?? 'openai';
|
|
3971
|
+
printChoiceGuide('Provider Choices', [
|
|
3972
|
+
{
|
|
3973
|
+
choice: 'mock',
|
|
3974
|
+
meaning: 'local development provider with no remote API key requirement',
|
|
3975
|
+
useWhen: 'you want to validate setup and runtime behavior before spending money on a remote model provider.',
|
|
3976
|
+
},
|
|
3977
|
+
{
|
|
3978
|
+
choice: 'openai / claude / gemini / groq / mistral',
|
|
3979
|
+
meaning: 'remote hosted model providers that need an upstream API key',
|
|
3980
|
+
useWhen: 'you want real model-backed Iranti behavior and already have a provider key.',
|
|
3981
|
+
},
|
|
3982
|
+
{
|
|
3983
|
+
choice: 'ollama',
|
|
3984
|
+
meaning: 'local Ollama runtime instead of a hosted provider',
|
|
3985
|
+
useWhen: 'you want local model execution and already run Ollama on the machine.',
|
|
3986
|
+
},
|
|
3987
|
+
]);
|
|
3932
3988
|
while (true) {
|
|
3933
3989
|
listProviderChoices(provider, existingInstance?.env ?? {});
|
|
3934
3990
|
const chosen = normalizeProvider(await promptNonEmpty(prompt, 'Default LLM provider', provider));
|
|
@@ -3987,10 +4043,20 @@ async function setupCommand(args) {
|
|
|
3987
4043
|
}
|
|
3988
4044
|
const projects = [];
|
|
3989
4045
|
const defaultProjectPath = process.cwd();
|
|
4046
|
+
printWizardNotes('Project Binding', [
|
|
4047
|
+
'Binding a project writes `.env.iranti` into one specific repo or app folder.',
|
|
4048
|
+
'Use the project root that should contain the binding file, not a broad parent folder like your whole `Projects` directory.',
|
|
4049
|
+
'In shared mode you can bind multiple repos to the same instance. In isolated mode you normally bind one repo.',
|
|
4050
|
+
]);
|
|
3990
4051
|
let shouldBindProject = await promptYesNo(prompt, 'Bind a project folder to this instance now?', true);
|
|
3991
4052
|
while (shouldBindProject) {
|
|
3992
4053
|
const projectPath = path_1.default.resolve(await promptNonEmpty(prompt, 'Project path to bind', projects.length === 0 ? defaultProjectPath : process.cwd()));
|
|
3993
4054
|
const agentId = sanitizeIdentifier(await promptNonEmpty(prompt, 'Project agent ID', projectAgentDefault(projectPath)), 'project_main');
|
|
4055
|
+
printWizardNotes('Project Memory Entity', [
|
|
4056
|
+
'This is the durable memory namespace the project will use by default.',
|
|
4057
|
+
'Use a stable entity like `project/my_repo` when the repo should have its own long-lived shared memory identity.',
|
|
4058
|
+
'Use a narrower entity only when you intentionally want this project bound to some other memory namespace.',
|
|
4059
|
+
]);
|
|
3994
4060
|
const memoryEntity = await promptNonEmpty(prompt, 'Project memory entity', 'user/main');
|
|
3995
4061
|
const claudeCode = await promptYesNo(prompt, 'Create Claude Code project files here now?', true);
|
|
3996
4062
|
projects.push({
|
|
@@ -4007,6 +4073,13 @@ async function setupCommand(args) {
|
|
|
4007
4073
|
shouldBindProject = false;
|
|
4008
4074
|
}
|
|
4009
4075
|
}
|
|
4076
|
+
if (projects.length > 0 && hasCodexInstalled()) {
|
|
4077
|
+
printWizardNotes('Codex Registration', [
|
|
4078
|
+
'This registers Iranti with the global Codex CLI MCP config.',
|
|
4079
|
+
'Say yes when this machine should let Codex call Iranti tools from bound projects.',
|
|
4080
|
+
'Say no if you are not using Codex yet or do not want to touch the global Codex config right now.',
|
|
4081
|
+
]);
|
|
4082
|
+
}
|
|
4010
4083
|
const codex = projects.length > 0 && hasCodexInstalled()
|
|
4011
4084
|
? await promptYesNo(prompt, 'Register Codex globally for the first bound project now?', false)
|
|
4012
4085
|
: false;
|
|
@@ -4901,6 +4974,13 @@ async function configureInstanceCommand(args) {
|
|
|
4901
4974
|
let clearProviderKey = hasFlag(args, 'clear-provider-key');
|
|
4902
4975
|
if (hasFlag(args, 'interactive')) {
|
|
4903
4976
|
await withPromptSession(async (prompt) => {
|
|
4977
|
+
printWizardNotes('Interactive Instance Configuration', [
|
|
4978
|
+
'This updates one existing instance in place.',
|
|
4979
|
+
'API port controls where the Iranti API listens.',
|
|
4980
|
+
'DATABASE_URL points at the PostgreSQL database for this instance.',
|
|
4981
|
+
'LLM provider and provider key control which model backend Iranti uses.',
|
|
4982
|
+
'Iranti API key is the client credential other tools and project bindings use to authenticate.',
|
|
4983
|
+
]);
|
|
4904
4984
|
portRaw = await prompt.line('API port', portRaw ?? env.IRANTI_PORT);
|
|
4905
4985
|
dbUrl = await prompt.line('DATABASE_URL', dbUrl ?? env.DATABASE_URL);
|
|
4906
4986
|
providerInput = await prompt.line('LLM provider', providerInput ?? env.LLM_PROVIDER ?? 'mock');
|
|
@@ -5004,6 +5084,14 @@ async function configureProjectCommand(args) {
|
|
|
5004
5084
|
let explicitProjectMode = getFlag(args, 'mode');
|
|
5005
5085
|
if (hasFlag(args, 'interactive')) {
|
|
5006
5086
|
await withPromptSession(async (prompt) => {
|
|
5087
|
+
printWizardNotes('Interactive Project Configuration', [
|
|
5088
|
+
'This updates the `.env.iranti` binding inside one project folder.',
|
|
5089
|
+
'Instance name retargets the binding to a named local instance and derives URL/env metadata from it.',
|
|
5090
|
+
'Iranti URL and Project API key are the direct connection details the project will use.',
|
|
5091
|
+
'Project agent ID is the default agent identity for tools running from this repo.',
|
|
5092
|
+
'Project memory entity is the durable namespace the project will use for shared memory.',
|
|
5093
|
+
'Project mode should stay `isolated` for repo-local memory or `shared` only when this repo should intentionally share one instance with other repos.',
|
|
5094
|
+
]);
|
|
5007
5095
|
instanceName = await prompt.line('Instance name', instanceName);
|
|
5008
5096
|
explicitUrl = await prompt.line('Iranti URL', explicitUrl ?? existing.IRANTI_URL);
|
|
5009
5097
|
explicitApiKey = await prompt.secret('Project API key', explicitApiKey ?? existing.IRANTI_API_KEY);
|
|
@@ -5638,6 +5726,22 @@ function printOptionGuide(title, entries) {
|
|
|
5638
5726
|
}
|
|
5639
5727
|
console.log('');
|
|
5640
5728
|
}
|
|
5729
|
+
function printChoiceGuide(title, entries) {
|
|
5730
|
+
console.log(sectionTitle(title));
|
|
5731
|
+
for (const entry of entries) {
|
|
5732
|
+
console.log(` ${commandText(entry.choice)}`);
|
|
5733
|
+
console.log(` What it means: ${entry.meaning}`);
|
|
5734
|
+
console.log(` Use this when: ${entry.useWhen}`);
|
|
5735
|
+
}
|
|
5736
|
+
console.log('');
|
|
5737
|
+
}
|
|
5738
|
+
function printWizardNotes(title, lines) {
|
|
5739
|
+
console.log(sectionTitle(title));
|
|
5740
|
+
for (const line of lines) {
|
|
5741
|
+
console.log(` - ${line}`);
|
|
5742
|
+
}
|
|
5743
|
+
console.log('');
|
|
5744
|
+
}
|
|
5641
5745
|
function printHelp() {
|
|
5642
5746
|
const rows = [
|
|
5643
5747
|
{
|
|
@@ -144,7 +144,7 @@ async function main() {
|
|
|
144
144
|
await ensureDefaultAgent(iranti);
|
|
145
145
|
const server = new mcp_js_1.McpServer({
|
|
146
146
|
name: 'iranti-mcp',
|
|
147
|
-
version: '0.2.
|
|
147
|
+
version: '0.2.25',
|
|
148
148
|
});
|
|
149
149
|
server.registerTool('iranti_handshake', {
|
|
150
150
|
description: `Initialize or refresh an agent's working-memory brief for the current task.
|
package/dist/src/api/server.js
CHANGED
|
@@ -41,7 +41,7 @@ const INSTANCE_DIR = process.env.IRANTI_INSTANCE_DIR?.trim()
|
|
|
41
41
|
const INSTANCE_RUNTIME_FILE = process.env.IRANTI_INSTANCE_RUNTIME_FILE?.trim()
|
|
42
42
|
|| (INSTANCE_DIR ? (0, runtimeLifecycle_1.runtimeFileForInstance)(INSTANCE_DIR) : null);
|
|
43
43
|
const INSTANCE_NAME = process.env.IRANTI_INSTANCE_NAME?.trim() || (INSTANCE_DIR ? path_1.default.basename(INSTANCE_DIR) : 'adhoc');
|
|
44
|
-
const VERSION = '0.2.
|
|
44
|
+
const VERSION = '0.2.25';
|
|
45
45
|
// M-18: Warn at startup if API key pepper is not set (important for production security)
|
|
46
46
|
if (!process.env.IRANTI_API_KEY_PEPPER) {
|
|
47
47
|
console.warn('[security] WARNING: IRANTI_API_KEY_PEPPER is not set. API key hashes have no pepper — set this env var in production.');
|