release: v2.0.7 - Enhanced Telegram Reporting & File Visibility (2026-05-14)

This commit is contained in:
g1nation
2026-05-14 00:37:41 +09:00
parent f1d5dbf031
commit 8104caf8d9
11 changed files with 187 additions and 20 deletions
+4
View File
@@ -195,6 +195,7 @@ export async function runCompanyTurn(
outputs,
report: reportResult.report,
sessionTimestamp: timestamp,
sessionDir,
});
telegramOk = await reporter(tgText);
if (!telegramOk) telegramReason = 'delivery-failed';
@@ -284,10 +285,12 @@ async function _dispatchOne(
// hit disk / shell. The report (e.g. "✅ Created: foo.py") is
// appended to the response so the user sees what really happened.
let finalResponse = rawResponse || '_(empty response)_';
let actionReport: string[] | undefined;
const hasTag = !!rawResponse && _hasActionTag(rawResponse);
if (rawResponse && deps.executeActionTags && hasTag) {
try {
const report = await deps.executeActionTags(rawResponse);
actionReport = report;
if (report.length > 0) {
finalResponse = `${rawResponse}\n\n---\n**Action 실행 결과:**\n${report.map((r) => `- ${r}`).join('\n')}`;
}
@@ -322,6 +325,7 @@ async function _dispatchOne(
error: rawResponse
? (claimedButDidnt ? 'claimed-creation-no-tag' : undefined)
: 'empty-response',
actionReport,
};
} catch (e: any) {
const err = e?.message ?? String(e);
+33 -3
View File
@@ -105,7 +105,10 @@ export async function buildTelegramReporter(
/**
* Compose the per-turn Telegram message. Format mirrors Connect_origin's
* Secretary report so users moving between the two products see consistent
* notifications: header + brief + agent list + CEO synthesis + session id.
* notifications: header + brief + agent list + CEO synthesis + session id +
* **concrete file paths** so follow-up questions like "어디에 만들었어?"
* have a clean answer (the bot's previous answer "I don't have file system
* access" was the user-visible bug we're fixing here).
*
* The function is pure (no I/O) and exported separately so it can be unit-
* tested without touching VS Code APIs.
@@ -117,6 +120,9 @@ export function formatCompanyTelegramReport(opts: {
outputs: AgentTurnOutput[];
report: string;
sessionTimestamp: string;
/** Absolute path of the session directory — surfaced in the report so
* the user can locate generated files without asking the bot again. */
sessionDir: string;
}): string {
const company = opts.state.companyName || '1인 기업';
const header = `*📱 ${company} — 작업 라운드 보고*`;
@@ -130,9 +136,33 @@ export function formatCompanyTelegramReport(opts: {
return `${mark} ${def?.emoji ?? ''} ${def?.name ?? t.agent}`;
}).join('\n')
: '';
// Concrete artefacts: extract the file paths the action-tag executor
// actually wrote, so the user can copy-paste them into Finder or `cd` to
// the right place. Empty when no agent emitted file/command tags.
const artefactsLine = _formatArtefactsBlock(opts.outputs);
const reportBody = opts.report.trim()
? `\n\n${opts.report.trim().slice(0, REPORT_BUDGET)}`
: '';
const sessionLine = `\n\n_세션: ${opts.sessionTimestamp}_`;
return `${header}\n\n${cmdLine}${brief}${agentsLine}${reportBody}${sessionLine}`;
const sessionLine = `\n\n*세션 폴더:* \`${opts.sessionDir}\``;
return `${header}\n\n${cmdLine}${brief}${agentsLine}${artefactsLine}${reportBody}${sessionLine}`;
}
/**
* Pull a `*결과물:*` block out of the per-agent action reports. The
* executor emits lines like `"✅ Created: testtimer/timer.py"` —
* we re-format them with the workspace-relative path intact so the user
* can `cd <workspace>/testtimer` and find the file.
*/
function _formatArtefactsBlock(outputs: AgentTurnOutput[]): string {
const lines: string[] = [];
for (const out of outputs) {
if (!out.actionReport || out.actionReport.length === 0) continue;
for (const r of out.actionReport) {
// Keep success lines verbatim; trim long shell-output blocks.
const trimmed = r.length > 200 ? r.slice(0, 200) + '…' : r;
lines.push(`${trimmed}`);
}
}
if (lines.length === 0) return '';
return '\n\n*결과물:*\n' + lines.join('\n');
}
+7
View File
@@ -101,6 +101,13 @@ export interface AgentTurnOutput {
durationMs: number;
/** Populated when the dispatch failed; `response` then holds the error. */
error?: string;
/**
* Lines returned by the action-tag executor — e.g. `"✅ Created: testtimer/timer.py"`.
* Kept separate from `response` so downstream surfaces (Telegram mirror,
* sidebar chip) can extract concrete file paths instead of regex-scraping
* the prose. Empty / absent when the agent emitted no action tags.
*/
actionReport?: string[];
}
/** The whole result of a company turn — persisted under sessions/<timestamp>/. */