oh-my-claude-sisyphus 1.1.1 → 1.2.1
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/dist/cli/index.js +205 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/features/auto-update.d.ts +115 -0
- package/dist/features/auto-update.d.ts.map +1 -0
- package/dist/features/auto-update.js +326 -0
- package/dist/features/auto-update.js.map +1 -0
- package/dist/features/background-tasks.d.ts +99 -0
- package/dist/features/background-tasks.d.ts.map +1 -0
- package/dist/features/background-tasks.js +265 -0
- package/dist/features/background-tasks.js.map +1 -0
- package/dist/features/continuation-enforcement.d.ts +2 -1
- package/dist/features/continuation-enforcement.d.ts.map +1 -1
- package/dist/features/continuation-enforcement.js +4 -1
- package/dist/features/continuation-enforcement.js.map +1 -1
- package/dist/features/index.d.ts +1 -0
- package/dist/features/index.d.ts.map +1 -1
- package/dist/features/index.js +5 -0
- package/dist/features/index.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/installer/index.d.ts +63 -0
- package/dist/installer/index.d.ts.map +1 -0
- package/dist/installer/index.js +964 -0
- package/dist/installer/index.js.map +1 -0
- package/package.json +4 -3
- package/scripts/install.sh +95 -3
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-Update System
|
|
3
|
+
*
|
|
4
|
+
* Provides version checking and auto-update functionality for Oh-My-Claude-Sisyphus.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Check for new versions from GitHub releases
|
|
8
|
+
* - Download and install updates automatically
|
|
9
|
+
* - Store version metadata for installed components
|
|
10
|
+
* - Configurable update notifications
|
|
11
|
+
*/
|
|
12
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from 'fs';
|
|
13
|
+
import { join, dirname } from 'path';
|
|
14
|
+
import { homedir, tmpdir } from 'os';
|
|
15
|
+
import { execSync } from 'child_process';
|
|
16
|
+
/** GitHub repository information */
|
|
17
|
+
export const REPO_OWNER = 'Yeachan-Heo';
|
|
18
|
+
export const REPO_NAME = 'oh-my-claude-sisyphus';
|
|
19
|
+
export const GITHUB_API_URL = `https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}`;
|
|
20
|
+
export const GITHUB_RAW_URL = `https://raw.githubusercontent.com/${REPO_OWNER}/${REPO_NAME}`;
|
|
21
|
+
/** Installation paths */
|
|
22
|
+
export const CLAUDE_CONFIG_DIR = join(homedir(), '.claude');
|
|
23
|
+
export const VERSION_FILE = join(CLAUDE_CONFIG_DIR, '.sisyphus-version.json');
|
|
24
|
+
/**
|
|
25
|
+
* Read the current version metadata
|
|
26
|
+
*/
|
|
27
|
+
export function getInstalledVersion() {
|
|
28
|
+
if (!existsSync(VERSION_FILE)) {
|
|
29
|
+
// Try to detect version from package.json if installed via npm
|
|
30
|
+
try {
|
|
31
|
+
// Check if we can find the package in node_modules
|
|
32
|
+
const result = execSync('npm list -g oh-my-claude-sisyphus --json 2>/dev/null', {
|
|
33
|
+
encoding: 'utf-8',
|
|
34
|
+
timeout: 5000
|
|
35
|
+
});
|
|
36
|
+
const data = JSON.parse(result);
|
|
37
|
+
if (data.dependencies?.['oh-my-claude-sisyphus']?.version) {
|
|
38
|
+
return {
|
|
39
|
+
version: data.dependencies['oh-my-claude-sisyphus'].version,
|
|
40
|
+
installedAt: new Date().toISOString(),
|
|
41
|
+
installMethod: 'npm'
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Not installed via npm or command failed
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const content = readFileSync(VERSION_FILE, 'utf-8');
|
|
52
|
+
return JSON.parse(content);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.error('Error reading version file:', error);
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Save version metadata after installation/update
|
|
61
|
+
*/
|
|
62
|
+
export function saveVersionMetadata(metadata) {
|
|
63
|
+
const dir = dirname(VERSION_FILE);
|
|
64
|
+
if (!existsSync(dir)) {
|
|
65
|
+
mkdirSync(dir, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
writeFileSync(VERSION_FILE, JSON.stringify(metadata, null, 2));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Update the last check timestamp
|
|
71
|
+
*/
|
|
72
|
+
export function updateLastCheckTime() {
|
|
73
|
+
const current = getInstalledVersion();
|
|
74
|
+
if (current) {
|
|
75
|
+
current.lastCheckAt = new Date().toISOString();
|
|
76
|
+
saveVersionMetadata(current);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Fetch the latest release from GitHub
|
|
81
|
+
*/
|
|
82
|
+
export async function fetchLatestRelease() {
|
|
83
|
+
const response = await fetch(`${GITHUB_API_URL}/releases/latest`, {
|
|
84
|
+
headers: {
|
|
85
|
+
'Accept': 'application/vnd.github.v3+json',
|
|
86
|
+
'User-Agent': 'oh-my-claude-sisyphus-updater'
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
if (response.status === 404) {
|
|
90
|
+
// No releases found - try to get version from package.json in repo
|
|
91
|
+
const pkgResponse = await fetch(`${GITHUB_RAW_URL}/main/package.json`, {
|
|
92
|
+
headers: {
|
|
93
|
+
'User-Agent': 'oh-my-claude-sisyphus-updater'
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
if (pkgResponse.ok) {
|
|
97
|
+
const pkg = await pkgResponse.json();
|
|
98
|
+
return {
|
|
99
|
+
tag_name: `v${pkg.version}`,
|
|
100
|
+
name: `Version ${pkg.version}`,
|
|
101
|
+
published_at: new Date().toISOString(),
|
|
102
|
+
html_url: `https://github.com/${REPO_OWNER}/${REPO_NAME}`,
|
|
103
|
+
body: 'No release notes available (fetched from package.json)',
|
|
104
|
+
prerelease: false,
|
|
105
|
+
draft: false
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
throw new Error('No releases found and could not fetch package.json');
|
|
109
|
+
}
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
throw new Error(`Failed to fetch release info: ${response.status} ${response.statusText}`);
|
|
112
|
+
}
|
|
113
|
+
return await response.json();
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Compare semantic versions
|
|
117
|
+
* Returns: -1 if a < b, 0 if a == b, 1 if a > b
|
|
118
|
+
*/
|
|
119
|
+
export function compareVersions(a, b) {
|
|
120
|
+
// Remove 'v' prefix if present
|
|
121
|
+
const cleanA = a.replace(/^v/, '');
|
|
122
|
+
const cleanB = b.replace(/^v/, '');
|
|
123
|
+
const partsA = cleanA.split('.').map(n => parseInt(n, 10) || 0);
|
|
124
|
+
const partsB = cleanB.split('.').map(n => parseInt(n, 10) || 0);
|
|
125
|
+
const maxLength = Math.max(partsA.length, partsB.length);
|
|
126
|
+
for (let i = 0; i < maxLength; i++) {
|
|
127
|
+
const numA = partsA[i] || 0;
|
|
128
|
+
const numB = partsB[i] || 0;
|
|
129
|
+
if (numA < numB)
|
|
130
|
+
return -1;
|
|
131
|
+
if (numA > numB)
|
|
132
|
+
return 1;
|
|
133
|
+
}
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check for available updates
|
|
138
|
+
*/
|
|
139
|
+
export async function checkForUpdates() {
|
|
140
|
+
const installed = getInstalledVersion();
|
|
141
|
+
const release = await fetchLatestRelease();
|
|
142
|
+
const currentVersion = installed?.version ?? null;
|
|
143
|
+
const latestVersion = release.tag_name.replace(/^v/, '');
|
|
144
|
+
const updateAvailable = currentVersion === null || compareVersions(currentVersion, latestVersion) < 0;
|
|
145
|
+
// Update last check time
|
|
146
|
+
updateLastCheckTime();
|
|
147
|
+
return {
|
|
148
|
+
currentVersion,
|
|
149
|
+
latestVersion,
|
|
150
|
+
updateAvailable,
|
|
151
|
+
releaseInfo: release,
|
|
152
|
+
releaseNotes: release.body || 'No release notes available.'
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Download and execute the install script to perform an update
|
|
157
|
+
*/
|
|
158
|
+
export async function performUpdate(options) {
|
|
159
|
+
const installed = getInstalledVersion();
|
|
160
|
+
const previousVersion = installed?.version ?? null;
|
|
161
|
+
try {
|
|
162
|
+
// Fetch the latest release to get the version
|
|
163
|
+
const release = await fetchLatestRelease();
|
|
164
|
+
const newVersion = release.tag_name.replace(/^v/, '');
|
|
165
|
+
// Download the install script
|
|
166
|
+
const installScriptUrl = `${GITHUB_RAW_URL}/main/scripts/install.sh`;
|
|
167
|
+
const response = await fetch(installScriptUrl);
|
|
168
|
+
if (!response.ok) {
|
|
169
|
+
throw new Error(`Failed to download install script: ${response.status}`);
|
|
170
|
+
}
|
|
171
|
+
const scriptContent = await response.text();
|
|
172
|
+
// Save to a temporary file
|
|
173
|
+
const tempDir = tmpdir();
|
|
174
|
+
const tempScript = join(tempDir, `sisyphus-update-${Date.now()}.sh`);
|
|
175
|
+
writeFileSync(tempScript, scriptContent, { mode: 0o755 });
|
|
176
|
+
// Execute the install script
|
|
177
|
+
try {
|
|
178
|
+
execSync(`bash "${tempScript}"`, {
|
|
179
|
+
encoding: 'utf-8',
|
|
180
|
+
stdio: options?.verbose ? 'inherit' : 'pipe',
|
|
181
|
+
timeout: 60000 // 1 minute timeout
|
|
182
|
+
});
|
|
183
|
+
// Update version metadata
|
|
184
|
+
saveVersionMetadata({
|
|
185
|
+
version: newVersion,
|
|
186
|
+
installedAt: new Date().toISOString(),
|
|
187
|
+
installMethod: 'script',
|
|
188
|
+
lastCheckAt: new Date().toISOString()
|
|
189
|
+
});
|
|
190
|
+
// Clean up temp file
|
|
191
|
+
try {
|
|
192
|
+
unlinkSync(tempScript);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// Ignore cleanup errors
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
success: true,
|
|
199
|
+
previousVersion,
|
|
200
|
+
newVersion,
|
|
201
|
+
message: `Successfully updated from ${previousVersion ?? 'unknown'} to ${newVersion}`
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
// Clean up temp file on error too
|
|
206
|
+
try {
|
|
207
|
+
unlinkSync(tempScript);
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Ignore cleanup errors
|
|
211
|
+
}
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
217
|
+
return {
|
|
218
|
+
success: false,
|
|
219
|
+
previousVersion,
|
|
220
|
+
newVersion: 'unknown',
|
|
221
|
+
message: `Update failed: ${errorMessage}`,
|
|
222
|
+
errors: [errorMessage]
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Get a formatted update notification message
|
|
228
|
+
*/
|
|
229
|
+
export function formatUpdateNotification(checkResult) {
|
|
230
|
+
if (!checkResult.updateAvailable) {
|
|
231
|
+
return `Oh-My-Claude-Sisyphus is up to date (v${checkResult.currentVersion ?? 'unknown'})`;
|
|
232
|
+
}
|
|
233
|
+
const lines = [
|
|
234
|
+
'╔═══════════════════════════════════════════════════════════╗',
|
|
235
|
+
'║ Oh-My-Claude-Sisyphus Update Available! ║',
|
|
236
|
+
'╚═══════════════════════════════════════════════════════════╝',
|
|
237
|
+
'',
|
|
238
|
+
` Current version: ${checkResult.currentVersion ?? 'unknown'}`,
|
|
239
|
+
` Latest version: ${checkResult.latestVersion}`,
|
|
240
|
+
'',
|
|
241
|
+
' To update, run: /update',
|
|
242
|
+
' Or run: curl -fsSL https://raw.githubusercontent.com/Yeachan-Heo/oh-my-claude-sisyphus/main/scripts/install.sh | bash',
|
|
243
|
+
''
|
|
244
|
+
];
|
|
245
|
+
// Add truncated release notes if available
|
|
246
|
+
if (checkResult.releaseNotes && checkResult.releaseNotes !== 'No release notes available.') {
|
|
247
|
+
lines.push(' Release notes:');
|
|
248
|
+
const notes = checkResult.releaseNotes.split('\n').slice(0, 5);
|
|
249
|
+
notes.forEach(line => lines.push(` ${line}`));
|
|
250
|
+
if (checkResult.releaseNotes.split('\n').length > 5) {
|
|
251
|
+
lines.push(' ...');
|
|
252
|
+
}
|
|
253
|
+
lines.push('');
|
|
254
|
+
}
|
|
255
|
+
return lines.join('\n');
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Check if enough time has passed since the last update check
|
|
259
|
+
*/
|
|
260
|
+
export function shouldCheckForUpdates(intervalHours = 24) {
|
|
261
|
+
const installed = getInstalledVersion();
|
|
262
|
+
if (!installed?.lastCheckAt) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
const lastCheck = new Date(installed.lastCheckAt).getTime();
|
|
266
|
+
const now = Date.now();
|
|
267
|
+
const hoursSinceLastCheck = (now - lastCheck) / (1000 * 60 * 60);
|
|
268
|
+
return hoursSinceLastCheck >= intervalHours;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Perform a background update check (non-blocking)
|
|
272
|
+
*/
|
|
273
|
+
export function backgroundUpdateCheck(callback) {
|
|
274
|
+
if (!shouldCheckForUpdates()) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
// Run the check asynchronously without blocking
|
|
278
|
+
checkForUpdates()
|
|
279
|
+
.then(result => {
|
|
280
|
+
if (callback) {
|
|
281
|
+
callback(result);
|
|
282
|
+
}
|
|
283
|
+
else if (result.updateAvailable) {
|
|
284
|
+
// Default behavior: print notification to console
|
|
285
|
+
console.log('\n' + formatUpdateNotification(result));
|
|
286
|
+
}
|
|
287
|
+
})
|
|
288
|
+
.catch(error => {
|
|
289
|
+
// Silently ignore errors in background checks
|
|
290
|
+
if (process.env.SISYPHUS_DEBUG) {
|
|
291
|
+
console.error('Background update check failed:', error);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* CLI helper: perform interactive update
|
|
297
|
+
*/
|
|
298
|
+
export async function interactiveUpdate() {
|
|
299
|
+
console.log('Checking for updates...');
|
|
300
|
+
try {
|
|
301
|
+
const checkResult = await checkForUpdates();
|
|
302
|
+
if (!checkResult.updateAvailable) {
|
|
303
|
+
console.log(`✓ You are running the latest version (${checkResult.currentVersion})`);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
console.log(formatUpdateNotification(checkResult));
|
|
307
|
+
console.log('Starting update...\n');
|
|
308
|
+
const result = await performUpdate({ verbose: true });
|
|
309
|
+
if (result.success) {
|
|
310
|
+
console.log(`\n✓ ${result.message}`);
|
|
311
|
+
console.log('\nPlease restart your Claude Code session to use the new version.');
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
console.error(`\n✗ ${result.message}`);
|
|
315
|
+
if (result.errors) {
|
|
316
|
+
result.errors.forEach(err => console.error(` - ${err}`));
|
|
317
|
+
}
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
console.error('Update check failed:', error instanceof Error ? error.message : error);
|
|
323
|
+
process.exit(1);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
//# sourceMappingURL=auto-update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-update.js","sourceRoot":"","sources":["../../src/features/auto-update.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background Task Management
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for managing background task execution,
|
|
5
|
+
* similar to oh-my-opencode's Background Task Manager.
|
|
6
|
+
*
|
|
7
|
+
* In Claude Code, background execution is controlled via:
|
|
8
|
+
* - Bash tool's `run_in_background` parameter
|
|
9
|
+
* - Task tool's `run_in_background` parameter
|
|
10
|
+
* - TaskOutput tool for retrieving results
|
|
11
|
+
*
|
|
12
|
+
* This module provides:
|
|
13
|
+
* - Decision heuristics for when to use background execution
|
|
14
|
+
* - Task lifecycle management
|
|
15
|
+
* - Concurrency limit enforcement
|
|
16
|
+
* - System prompt guidance for agents
|
|
17
|
+
*/
|
|
18
|
+
import type { BackgroundTask, SessionState, PluginConfig } from '../shared/types.js';
|
|
19
|
+
/**
|
|
20
|
+
* Default maximum concurrent background tasks
|
|
21
|
+
*/
|
|
22
|
+
export declare const DEFAULT_MAX_BACKGROUND_TASKS = 5;
|
|
23
|
+
/**
|
|
24
|
+
* Patterns that indicate long-running operations
|
|
25
|
+
* These should typically run in background
|
|
26
|
+
*/
|
|
27
|
+
export declare const LONG_RUNNING_PATTERNS: RegExp[];
|
|
28
|
+
/**
|
|
29
|
+
* Patterns that should always run blocking (foreground)
|
|
30
|
+
* These are quick operations or need immediate feedback
|
|
31
|
+
*/
|
|
32
|
+
export declare const BLOCKING_PATTERNS: RegExp[];
|
|
33
|
+
/**
|
|
34
|
+
* Result of background execution decision
|
|
35
|
+
*/
|
|
36
|
+
export interface TaskExecutionDecision {
|
|
37
|
+
/** Whether to run in background */
|
|
38
|
+
runInBackground: boolean;
|
|
39
|
+
/** Human-readable reason for the decision */
|
|
40
|
+
reason: string;
|
|
41
|
+
/** Estimated duration category */
|
|
42
|
+
estimatedDuration: 'quick' | 'medium' | 'long' | 'unknown';
|
|
43
|
+
/** Confidence level of the decision */
|
|
44
|
+
confidence: 'high' | 'medium' | 'low';
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Determine if a command should run in background
|
|
48
|
+
*
|
|
49
|
+
* This is the core heuristic function that decides whether a command
|
|
50
|
+
* should be executed with `run_in_background: true`.
|
|
51
|
+
*
|
|
52
|
+
* @param command - The command to analyze
|
|
53
|
+
* @param currentBackgroundCount - Number of currently running background tasks
|
|
54
|
+
* @param maxBackgroundTasks - Maximum allowed concurrent background tasks
|
|
55
|
+
* @returns Decision object with recommendation and reasoning
|
|
56
|
+
*/
|
|
57
|
+
export declare function shouldRunInBackground(command: string, currentBackgroundCount?: number, maxBackgroundTasks?: number): TaskExecutionDecision;
|
|
58
|
+
/**
|
|
59
|
+
* BackgroundTaskManager interface
|
|
60
|
+
*
|
|
61
|
+
* Manages background task lifecycle, enforces concurrency limits,
|
|
62
|
+
* and provides utilities for tracking task status.
|
|
63
|
+
*/
|
|
64
|
+
export interface BackgroundTaskManager {
|
|
65
|
+
/** Register a new background task */
|
|
66
|
+
registerTask(agentName: string, prompt: string): BackgroundTask;
|
|
67
|
+
/** Get all background tasks */
|
|
68
|
+
getTasks(): BackgroundTask[];
|
|
69
|
+
/** Get tasks by status */
|
|
70
|
+
getTasksByStatus(status: BackgroundTask['status']): BackgroundTask[];
|
|
71
|
+
/** Get count of running tasks */
|
|
72
|
+
getRunningCount(): number;
|
|
73
|
+
/** Check if we can start a new background task */
|
|
74
|
+
canStartNewTask(): boolean;
|
|
75
|
+
/** Update task status */
|
|
76
|
+
updateTaskStatus(taskId: string, status: BackgroundTask['status'], result?: string, error?: string): void;
|
|
77
|
+
/** Mark task as completed */
|
|
78
|
+
completeTask(taskId: string, result: string): void;
|
|
79
|
+
/** Mark task as failed */
|
|
80
|
+
failTask(taskId: string, error: string): void;
|
|
81
|
+
/** Remove completed tasks older than specified age (ms) */
|
|
82
|
+
pruneCompletedTasks(maxAge?: number): number;
|
|
83
|
+
/** Get the maximum allowed background tasks */
|
|
84
|
+
getMaxTasks(): number;
|
|
85
|
+
/** Check if a command should run in background */
|
|
86
|
+
shouldRunInBackground(command: string): TaskExecutionDecision;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Create a BackgroundTaskManager instance
|
|
90
|
+
*/
|
|
91
|
+
export declare function createBackgroundTaskManager(state: SessionState, config: PluginConfig): BackgroundTaskManager;
|
|
92
|
+
/**
|
|
93
|
+
* System prompt guidance for background task execution
|
|
94
|
+
*
|
|
95
|
+
* This text should be appended to the system prompt to guide agents
|
|
96
|
+
* on when and how to use background execution.
|
|
97
|
+
*/
|
|
98
|
+
export declare function getBackgroundTaskGuidance(maxBackgroundTasks?: number): string;
|
|
99
|
+
//# sourceMappingURL=background-tasks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-tasks.d.ts","sourceRoot":"","sources":["../../src/features/background-tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAErF;;GAEG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,UAuCjC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,UA0B7B,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,mCAAmC;IACnC,eAAe,EAAE,OAAO,CAAC;IACzB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,iBAAiB,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IAC3D,uCAAuC;IACvC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACvC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,sBAAsB,GAAE,MAAU,EAClC,kBAAkB,GAAE,MAAqC,GACxD,qBAAqB,CAoDvB;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,qCAAqC;IACrC,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC;IAEhE,+BAA+B;IAC/B,QAAQ,IAAI,cAAc,EAAE,CAAC;IAE7B,0BAA0B;IAC1B,gBAAgB,CAAC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,cAAc,EAAE,CAAC;IAErE,iCAAiC;IACjC,eAAe,IAAI,MAAM,CAAC;IAE1B,kDAAkD;IAClD,eAAe,IAAI,OAAO,CAAC;IAE3B,yBAAyB;IACzB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1G,6BAA6B;IAC7B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAEnD,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9C,2DAA2D;IAC3D,mBAAmB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE7C,+CAA+C;IAC/C,WAAW,IAAI,MAAM,CAAC;IAEtB,kDAAkD;IAClD,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAAC;CAC/D;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,YAAY,GACnB,qBAAqB,CAkEvB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,kBAAkB,GAAE,MAAqC,GAAG,MAAM,CAkD3G"}
|