[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
232
infrastructure/scripts/nctMonacoCompletion.ts
Normal file
232
infrastructure/scripts/nctMonacoCompletion.ts
Normal file
@@ -0,0 +1,232 @@
|
||||
import type { Monaco } from '@monaco-editor/react';
|
||||
|
||||
type CompletionDisposable = { dispose: () => void };
|
||||
|
||||
const NCT_API_COMPLETIONS = [
|
||||
{
|
||||
label: 'nct.screen.waitForPrompt',
|
||||
sortText: 'nct.screen.waitFor.00.prompt',
|
||||
insertText: 'await nct.screen.waitForPrompt(${1:30000});',
|
||||
detail: 'Wait for shell prompt',
|
||||
documentation: 'Wait until an interactive shell prompt appears (# for root, $ for regular user).',
|
||||
},
|
||||
{
|
||||
label: 'nct.screen.waitForText',
|
||||
sortText: 'nct.screen.waitFor.01.text',
|
||||
insertText: "await nct.screen.waitForText('${1:text}', ${2:30000});",
|
||||
detail: 'Wait for literal text',
|
||||
documentation: 'Wait until the exact text appears in session output. Regex characters are treated as normal text.',
|
||||
},
|
||||
{
|
||||
label: 'nct.screen.waitForRegex',
|
||||
sortText: 'nct.screen.waitFor.02.regex',
|
||||
insertText: "await nct.screen.waitForRegex('${1:pattern}', ${2:30000});",
|
||||
detail: 'Wait for regex match',
|
||||
documentation: 'Wait until session output matches a regular expression. String patterns use dotAll matching for multiline output.',
|
||||
},
|
||||
{
|
||||
label: 'nct.screen.waitFor',
|
||||
sortText: 'nct.screen.waitFor.03.legacy',
|
||||
insertText: "await nct.screen.waitFor('${1:text}', ${2:30000});",
|
||||
detail: 'Wait for terminal output (legacy)',
|
||||
documentation: 'Compatibility helper. Plain string patterns are literal; legacy /regex/flags strings still work, but prefer waitForText for text or waitForRegex for regular expressions.',
|
||||
},
|
||||
{
|
||||
label: 'nct.screen.waitForAny',
|
||||
insertText: "await nct.screen.waitForAny(['# ', '$ ', '~# ', '~$ '], ${1:30000});",
|
||||
detail: 'Wait for any pattern',
|
||||
documentation: 'Wait until any of the given patterns appears in session output.',
|
||||
},
|
||||
{
|
||||
label: 'nct.screen.sendLine',
|
||||
insertText: "await nct.screen.sendLine('${1:command}');",
|
||||
detail: 'Send line + Enter',
|
||||
documentation: 'Send text to the terminal followed by carriage return.',
|
||||
},
|
||||
{
|
||||
label: 'nct.screen.send',
|
||||
insertText: "await nct.screen.send('${1:text}');",
|
||||
detail: 'Send text',
|
||||
documentation: 'Send text to the terminal without pressing Enter.',
|
||||
},
|
||||
{
|
||||
label: 'nct.screen.getText',
|
||||
insertText: 'const output = await nct.screen.getText();',
|
||||
detail: 'Read terminal text',
|
||||
documentation: 'Read visible terminal buffer text or a row range.',
|
||||
},
|
||||
{
|
||||
label: 'nct.screen.clear',
|
||||
insertText: 'await nct.screen.clear();',
|
||||
detail: 'Clear terminal screen',
|
||||
documentation: 'Send a clear-screen sequence to the terminal.',
|
||||
},
|
||||
{
|
||||
label: 'nct.session.sleep',
|
||||
insertText: 'await nct.session.sleep(${1:1000});',
|
||||
detail: 'Pause script',
|
||||
documentation: 'Pause script execution for the given milliseconds.',
|
||||
},
|
||||
{
|
||||
label: 'nct.sleep',
|
||||
insertText: 'await nct.sleep(${1:1000});',
|
||||
detail: 'Pause script',
|
||||
documentation: 'Alias for nct.session.sleep.',
|
||||
},
|
||||
{
|
||||
label: 'nct.session.startLog',
|
||||
insertText: "await nct.session.startLog('${1:./script.log}');",
|
||||
detail: 'Start session log',
|
||||
documentation: 'Start writing session output to a local log file.',
|
||||
},
|
||||
{
|
||||
label: 'nct.session.stopLog',
|
||||
insertText: 'await nct.session.stopLog();',
|
||||
detail: 'Stop session log',
|
||||
documentation: 'Stop the active script log stream.',
|
||||
},
|
||||
{
|
||||
label: 'nct.session.disconnect',
|
||||
insertText: 'await nct.session.disconnect();',
|
||||
detail: 'Disconnect session',
|
||||
documentation: 'Close the current terminal session.',
|
||||
},
|
||||
{
|
||||
label: 'nct.dialog.confirm',
|
||||
insertText: "const ok = await nct.dialog.confirm('${1:Continue?}');",
|
||||
detail: 'Confirm dialog',
|
||||
documentation: 'Show a confirm dialog and return true when accepted.',
|
||||
},
|
||||
{
|
||||
label: 'nct.dialog.prompt',
|
||||
insertText: "const value = await nct.dialog.prompt('${1:Input}', '${2:}');",
|
||||
detail: 'Prompt dialog',
|
||||
documentation: 'Show an input dialog and return the entered string.',
|
||||
},
|
||||
{
|
||||
label: 'nct.dialog.alert',
|
||||
insertText: "await nct.dialog.alert('${1:Message}');",
|
||||
detail: 'Alert dialog',
|
||||
documentation: 'Show an informational alert dialog.',
|
||||
},
|
||||
{
|
||||
label: 'nct.dialog.form',
|
||||
insertText: [
|
||||
'const values = await nct.dialog.form({',
|
||||
" title: '${1:Options}',",
|
||||
" message: '${2:Choose how to continue}',",
|
||||
' fields: [',
|
||||
" { type: 'select', name: '${3:env}', label: '${4:Environment}', options: ['${5:dev}', '${6:prod}'], defaultValue: '${5:dev}' },",
|
||||
" { type: 'checkbox', name: '${7:restart}', label: '${8:Restart service}', defaultValue: true },",
|
||||
" { type: 'textarea', name: '${9:notes}', label: '${10:Notes}', required: false, visibleWhen: { field: '${3:env}', notEquals: '${5:dev}' } },",
|
||||
" { type: 'number', name: '${11:retries}', label: '${12:Retries}', defaultValue: 3, min: 0, step: 1 },",
|
||||
' ],',
|
||||
'});',
|
||||
].join('\n'),
|
||||
detail: 'Form dialog',
|
||||
documentation: 'Show a form dialog with select, checkbox, radio, textarea, and number fields. Fields can use visibleWhen for conditional display. Returns an object keyed by visible field name.',
|
||||
},
|
||||
{
|
||||
label: 'nct.dialog.select',
|
||||
insertText: "const value = await nct.dialog.select('${1:Choose one}', ['${2:first}', '${3:second}'], '${2:first}');",
|
||||
detail: 'Select dialog',
|
||||
documentation: 'Show a single-select dialog and return the selected option value.',
|
||||
},
|
||||
{
|
||||
label: 'nct.dialog.radio',
|
||||
insertText: "const value = await nct.dialog.radio('${1:Choose one}', ['${2:first}', '${3:second}'], '${2:first}');",
|
||||
detail: 'Radio dialog',
|
||||
documentation: 'Show a radio-choice dialog and return the selected option value.',
|
||||
},
|
||||
{
|
||||
label: 'nct.dialog.checkbox',
|
||||
insertText: "const checked = await nct.dialog.checkbox('${1:Enable option}', ${2:true});",
|
||||
detail: 'Checkbox dialog',
|
||||
documentation: 'Show a checkbox dialog and return whether it is checked.',
|
||||
},
|
||||
{
|
||||
label: 'nct.log',
|
||||
insertText: "nct.log('${1:message}');",
|
||||
detail: 'Script log',
|
||||
documentation: 'Append a line to the script run log panel.',
|
||||
},
|
||||
{
|
||||
label: 'nct.progress.start',
|
||||
insertText: "nct.progress.start('${1:Phase name}', ${2:total});",
|
||||
detail: 'Start determinate progress',
|
||||
documentation: 'Opt in to a labeled X/Y progress bar for known-length loops.',
|
||||
},
|
||||
{
|
||||
label: 'nct.progress.step',
|
||||
insertText: "nct.progress.step('${1:detail}');",
|
||||
detail: 'Advance progress',
|
||||
documentation: 'Increment determinate progress by one step.',
|
||||
},
|
||||
{
|
||||
label: 'nct.progress.set',
|
||||
insertText: "nct.progress.set(${1:current}, '${2:detail}');",
|
||||
detail: 'Set progress position',
|
||||
documentation: 'Set determinate progress to a specific index.',
|
||||
},
|
||||
{
|
||||
label: 'nct.progress.done',
|
||||
insertText: 'nct.progress.done();',
|
||||
detail: 'Finish progress phase',
|
||||
documentation: 'Complete the current determinate progress phase.',
|
||||
},
|
||||
];
|
||||
|
||||
let registered = false;
|
||||
let disposable: CompletionDisposable | null = null;
|
||||
|
||||
export function registerNctMonacoCompletionProvider(monaco: Monaco): CompletionDisposable {
|
||||
if (registered && disposable) {
|
||||
return disposable;
|
||||
}
|
||||
|
||||
disposable = monaco.languages.registerCompletionItemProvider('javascript', {
|
||||
triggerCharacters: ['.', '('],
|
||||
provideCompletionItems: (model, position) => {
|
||||
const word = model.getWordUntilPosition(position);
|
||||
const range = {
|
||||
startLineNumber: position.lineNumber,
|
||||
endLineNumber: position.lineNumber,
|
||||
startColumn: word.startColumn,
|
||||
endColumn: word.endColumn,
|
||||
};
|
||||
const prefix = model.getValueInRange({
|
||||
startLineNumber: position.lineNumber,
|
||||
startColumn: 1,
|
||||
endLineNumber: position.lineNumber,
|
||||
endColumn: position.column,
|
||||
});
|
||||
|
||||
const suggestions = NCT_API_COMPLETIONS
|
||||
.filter((item) => {
|
||||
if (prefix.trim().length === 0) return true;
|
||||
return item.label.startsWith('nct') && prefix.includes('nct');
|
||||
})
|
||||
.map((item) => ({
|
||||
label: item.label,
|
||||
kind: monaco.languages.CompletionItemKind.Method,
|
||||
insertText: item.insertText,
|
||||
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
detail: item.detail,
|
||||
documentation: item.documentation,
|
||||
sortText: item.sortText ?? item.label,
|
||||
range,
|
||||
}));
|
||||
|
||||
return { suggestions };
|
||||
},
|
||||
});
|
||||
|
||||
registered = true;
|
||||
return disposable;
|
||||
}
|
||||
|
||||
export function disposeNctMonacoCompletionProvider() {
|
||||
disposable?.dispose();
|
||||
disposable = null;
|
||||
registered = false;
|
||||
}
|
||||
35
infrastructure/scripts/screenSnapshotRegistry.ts
Normal file
35
infrastructure/scripts/screenSnapshotRegistry.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
export type ScreenSnapshotProvider = () => {
|
||||
rows: number;
|
||||
cols: number;
|
||||
currentRow: number;
|
||||
lines: string[];
|
||||
/** Optional origin marker (e.g. hibernate-viewport). */
|
||||
source?: string;
|
||||
};
|
||||
|
||||
const providers = new Map<string, ScreenSnapshotProvider>();
|
||||
|
||||
export function registerScreenSnapshotProvider(
|
||||
sessionId: string,
|
||||
provider: ScreenSnapshotProvider,
|
||||
): () => void {
|
||||
providers.set(sessionId, provider);
|
||||
return () => {
|
||||
if (providers.get(sessionId) === provider) {
|
||||
providers.delete(sessionId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function captureScreenSnapshot(sessionId: string) {
|
||||
const provider = providers.get(sessionId);
|
||||
if (!provider) {
|
||||
return {
|
||||
rows: 24,
|
||||
cols: 80,
|
||||
currentRow: 0,
|
||||
lines: [] as string[],
|
||||
};
|
||||
}
|
||||
return provider();
|
||||
}
|
||||
Reference in New Issue
Block a user