gsd-pi 0.3.1 → 2.3.4
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/resource-loader.d.ts +3 -3
- package/dist/resource-loader.js +10 -4
- package/package.json +3 -1
- package/src/resources/extensions/browser-tools/index.ts +76 -6
- package/src/resources/extensions/gsd/auto.ts +188 -10
- package/src/resources/extensions/gsd/commands.ts +13 -6
- package/src/resources/extensions/gsd/doctor.ts +7 -0
- package/src/resources/extensions/gsd/guided-flow.ts +8 -5
- package/src/resources/extensions/gsd/index.ts +8 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +70 -26
- package/src/resources/extensions/gsd/prompts/worktree-merge.md +51 -17
- package/src/resources/extensions/gsd/worktree-command.ts +219 -49
- package/src/resources/extensions/gsd/worktree-manager.ts +106 -16
- package/src/resources/extensions/mcporter/index.ts +410 -0
- package/src/resources/extensions/slash-commands/clear.ts +10 -0
- package/src/resources/extensions/slash-commands/index.ts +2 -2
- package/src/resources/extensions/voice/index.ts +195 -0
- package/src/resources/extensions/voice/speech-recognizer.swift +76 -0
- package/src/resources/extensions/slash-commands/gsd-run.ts +0 -34
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Speech
|
|
3
|
+
import AVFoundation
|
|
4
|
+
|
|
5
|
+
// Unbuffered stdout
|
|
6
|
+
setbuf(stdout, nil)
|
|
7
|
+
|
|
8
|
+
guard SFSpeechRecognizer.authorizationStatus() == .authorized ||
|
|
9
|
+
SFSpeechRecognizer.authorizationStatus() == .notDetermined else {
|
|
10
|
+
print("ERROR:Speech recognition not authorized")
|
|
11
|
+
exit(1)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
SFSpeechRecognizer.requestAuthorization { status in
|
|
15
|
+
guard status == .authorized else {
|
|
16
|
+
print("ERROR:Speech recognition denied")
|
|
17
|
+
exit(1)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))!
|
|
22
|
+
guard recognizer.isAvailable else {
|
|
23
|
+
print("ERROR:Speech recognizer not available")
|
|
24
|
+
exit(1)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let audioEngine = AVAudioEngine()
|
|
28
|
+
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
29
|
+
request.shouldReportPartialResults = true
|
|
30
|
+
request.requiresOnDeviceRecognition = true
|
|
31
|
+
|
|
32
|
+
let node = audioEngine.inputNode
|
|
33
|
+
let format = node.outputFormat(forBus: 0)
|
|
34
|
+
|
|
35
|
+
node.installTap(onBus: 0, bufferSize: 1024, format: format) { buffer, _ in
|
|
36
|
+
request.append(buffer)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
audioEngine.prepare()
|
|
40
|
+
do {
|
|
41
|
+
try audioEngine.start()
|
|
42
|
+
print("READY")
|
|
43
|
+
} catch {
|
|
44
|
+
print("ERROR:Failed to start audio engine: \(error.localizedDescription)")
|
|
45
|
+
exit(1)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
var lastText = ""
|
|
49
|
+
|
|
50
|
+
recognizer.recognitionTask(with: request) { result, error in
|
|
51
|
+
if let result = result {
|
|
52
|
+
let text = result.bestTranscription.formattedString
|
|
53
|
+
if text != lastText {
|
|
54
|
+
lastText = text
|
|
55
|
+
let prefix = result.isFinal ? "FINAL" : "PARTIAL"
|
|
56
|
+
print("\(prefix):\(text)")
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if let error = error {
|
|
60
|
+
// Task finished errors are normal on kill
|
|
61
|
+
let nsError = error as NSError
|
|
62
|
+
if nsError.code != 216 { // kAFAssistantErrorDomain code for cancelled
|
|
63
|
+
print("ERROR:\(error.localizedDescription)")
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Handle SIGTERM/SIGINT gracefully
|
|
69
|
+
signal(SIGTERM) { _ in
|
|
70
|
+
exit(0)
|
|
71
|
+
}
|
|
72
|
+
signal(SIGINT) { _ in
|
|
73
|
+
exit(0)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
RunLoop.current.run()
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import type { ExtensionAPI, ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
|
|
4
|
-
|
|
5
|
-
export default function gsdRun(pi: ExtensionAPI) {
|
|
6
|
-
pi.registerCommand("gsd-run", {
|
|
7
|
-
description: "Read GSD-WORKFLOW.md and execute — lightweight protocol-driven GSD",
|
|
8
|
-
async handler(args: string, ctx: ExtensionCommandContext) {
|
|
9
|
-
const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(process.env.HOME ?? "~", ".pi", "GSD-WORKFLOW.md");
|
|
10
|
-
|
|
11
|
-
let workflow: string;
|
|
12
|
-
try {
|
|
13
|
-
workflow = readFileSync(workflowPath, "utf-8");
|
|
14
|
-
} catch {
|
|
15
|
-
ctx.ui.notify(`Cannot read ${workflowPath}`, "error");
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const userNote = (typeof args === "string" ? args : "").trim();
|
|
20
|
-
const noteSection = userNote
|
|
21
|
-
? `\n\n## User Note\n\n${userNote}\n`
|
|
22
|
-
: "";
|
|
23
|
-
|
|
24
|
-
pi.sendMessage(
|
|
25
|
-
{
|
|
26
|
-
customType: "gsd-run",
|
|
27
|
-
content: `Read the following GSD workflow protocol and execute exactly.\n\n${workflow}${noteSection}`,
|
|
28
|
-
display: false,
|
|
29
|
-
},
|
|
30
|
-
{ triggerTurn: true },
|
|
31
|
-
);
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
}
|