size. Always verify your model's actual supported context - exceeding
it causes unpredictable or significantly degraded model output.
+*** Timeout
+
+/Timeout/ is a parameter that specifies the maximum time (in
+milliseconds) that the AI is allowed to run for a task. If this time
+is exceeded, the process is terminated, and the response is marked
+with "TERMINATED BY TIMEOUT".
+
+The timeout parameter can be set at three levels:
+1. *Skill-specific*: Defined in the skill YAML file.
+2. *Model-specific*: Defined in the model configuration.
+3. *Global default*: Set in the main configuration file.
+
+The priority hierarchy is: *skill* > *model* > *global default*.
+
+For example, to set a 5-minute timeout (300,000 milliseconds) for a specific skill, add:
+: timeout_millis: 300000
+in the skill's YAML file.
+
+In the model configuration:
+#+begin_src yaml
+models:
+ - alias: "mistral"
+ timeout_millis: 600000
+ # ... other parameters
+#+end_src
+
+In the main configuration:
+#+begin_src yaml
+default_timeout_millis: 120000
+#+end_src
+
+Setting a timeout of 0 means no timeout.
+
+This feature helps prevent stuck AI processes and ensures predictable
+task completion times.
+
*** Parameter Precedence Hierarchy
:PROPERTIES:
:ID: 456dd42e-a474-4464-a14e-384c68713537
else return configuration.getDefaultMinP();
}
+ /**
+ * Calculates the effective timeout in milliseconds using the following hierarchy:
+ * <ol>
+ * <li>Skill-specific timeout (highest priority)</li>
+ * <li>Model-specific timeout</li>
+ * <li>Global default timeout (lowest priority)</li>
+ * </ol>
+ *
+ * @return the effective timeout in milliseconds, or null if no timeout is configured.
+ */
+ public Long getEffectiveTimeoutMillis() {
+ // Skill-specific has the highest priority
+ if (skill != null && skill.getTimeoutMillis() != null) {
+ return skill.getTimeoutMillis();
+ }
+
+ // Model-specific next
+ if (model.getTimeoutMillis() != null) {
+ return model.getTimeoutMillis();
+ }
+
+ // Global default as fallback
+ return configuration.getDefaultTimeoutMillis();
+ }
+
}
import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
import static eu.svjatoslav.alyverkko_cli.Main.configuration;
import static java.lang.String.join;
return task.systemPrompt.replace("<TASK-FILE>", task.userPrompt);
}
+
/**
* Runs the AI query by constructing the prompt, writing it to a temp file,
* invoking llama.cpp, collecting output, and performing any final cleanup.
StringBuilder result = new StringBuilder();
Thread outputThread = handleResultThread(process, result);
- // Wait for the process to finish
- process.waitFor();
+ // Get effective timeout value
+ Long timeoutMillis = task.getEffectiveTimeoutMillis();
+ boolean isTimedOut = false;
+
+ if (timeoutMillis != null && timeoutMillis > 0) {
+ try {
+ if (!process.waitFor(timeoutMillis, TimeUnit.MILLISECONDS)) {
+ process.destroyForcibly();
+ isTimedOut = true;
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ process.destroyForcibly();
+ isTimedOut = true;
+ }
+ } else {
+ process.waitFor();
+ }
// Wait for the output thread to finish reading
outputThread.join();
task.endTimeMillis = System.currentTimeMillis();
// Clean up the AI response: remove partial prompt text, end-of-text marker, etc.
- return cleanupAiResponse(result.toString());
+ String cleanedResponse = cleanupAiResponse(result.toString());
+ if (isTimedOut) {
+ cleanedResponse += "\nTERMINATED BY TIMEOUT";
+ }
+
+ return cleanedResponse;
} finally {
deleteTemporaryFile();
}
@JsonProperty("skills_directory")
private File skillsDirectory;
+ /**
+ * The default timeout in milliseconds for AI processing tasks. A value of 0 or null means no timeout.
+ * This serves as the lowest-priority fallback when no skill-specific or model-specific timeout is set.
+ */
+ @JsonProperty("default_timeout_millis")
+ private Long defaultTimeoutMillis;
+
+
/**
* The list of models defined in this configuration.
*/
@JsonProperty("final_answer_indicator")
private String finalAnswerIndicator;
+ /**
+ * Maximum time in milliseconds allowed for AI processing for this model. If null, no timeout is set for this model.
+ * This value overrides the global default timeout but is overridden by skill-specific timeouts.
+ */
+ @JsonProperty("timeout_millis")
+ private Long timeoutMillis;
+
/**
* <p>Prints the model's metadata to standard output in a consistent format. This includes the model's alias,
* filesystem path, and context token capacity. The output format is designed to be both human-readable and
@JsonProperty("model_alias")
private String modelAlias;
+ /**
+ * Maximum time in milliseconds allowed for AI processing when this skill is used. If null, no timeout is set for this skill.
+ * This is the highest-priority timeout value in the hierarchy, overriding model-specific and global default timeouts.
+ */
+ @JsonProperty("timeout_millis")
+ private Long timeoutMillis;
+
}
\ No newline at end of file