@aion0/forge 0.5.44 β†’ 0.5.46

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.
Files changed (58) hide show
  1. package/RELEASE_NOTES.md +3 -15
  2. package/package.json +1 -1
  3. package/tsconfig.json +3 -1
  4. package/intellij-plugin/README.md +0 -53
  5. package/intellij-plugin/build.gradle.kts +0 -60
  6. package/intellij-plugin/gradle/gradle-daemon-jvm.properties +0 -12
  7. package/intellij-plugin/gradle.properties +0 -9
  8. package/intellij-plugin/publish.sh +0 -78
  9. package/intellij-plugin/settings.gradle.kts +0 -7
  10. package/intellij-plugin/src/main/kotlin/com/aion0/forge/action/LoginAction.kt +0 -49
  11. package/intellij-plugin/src/main/kotlin/com/aion0/forge/action/LogoutAction.kt +0 -18
  12. package/intellij-plugin/src/main/kotlin/com/aion0/forge/action/OpenWebUIAction.kt +0 -13
  13. package/intellij-plugin/src/main/kotlin/com/aion0/forge/action/SwitchConnectionAction.kt +0 -26
  14. package/intellij-plugin/src/main/kotlin/com/aion0/forge/api/ForgeClient.kt +0 -115
  15. package/intellij-plugin/src/main/kotlin/com/aion0/forge/auth/Auth.kt +0 -31
  16. package/intellij-plugin/src/main/kotlin/com/aion0/forge/connection/ConnectionManager.kt +0 -95
  17. package/intellij-plugin/src/main/kotlin/com/aion0/forge/settings/ForgeConfigurable.kt +0 -81
  18. package/intellij-plugin/src/main/kotlin/com/aion0/forge/ui/toolwindow/DocsView.kt +0 -99
  19. package/intellij-plugin/src/main/kotlin/com/aion0/forge/ui/toolwindow/ForgeStatusBarWidgetFactory.kt +0 -94
  20. package/intellij-plugin/src/main/kotlin/com/aion0/forge/ui/toolwindow/ForgeToolWindowFactory.kt +0 -27
  21. package/intellij-plugin/src/main/kotlin/com/aion0/forge/ui/toolwindow/ForgeTreeView.kt +0 -176
  22. package/intellij-plugin/src/main/kotlin/com/aion0/forge/ui/toolwindow/Helpers.kt +0 -48
  23. package/intellij-plugin/src/main/kotlin/com/aion0/forge/ui/toolwindow/PipelinesView.kt +0 -226
  24. package/intellij-plugin/src/main/kotlin/com/aion0/forge/ui/toolwindow/TerminalsView.kt +0 -309
  25. package/intellij-plugin/src/main/kotlin/com/aion0/forge/ui/toolwindow/TreeNodeData.kt +0 -33
  26. package/intellij-plugin/src/main/kotlin/com/aion0/forge/ui/toolwindow/WorkspacesView.kt +0 -166
  27. package/intellij-plugin/src/main/resources/META-INF/plugin.xml +0 -88
  28. package/intellij-plugin/src/main/resources/icons/forge.svg +0 -3
  29. package/vscode-extension/.vscodeignore +0 -11
  30. package/vscode-extension/README.md +0 -48
  31. package/vscode-extension/media/icon.png +0 -0
  32. package/vscode-extension/media/icon.svg +0 -3
  33. package/vscode-extension/package-lock.json +0 -4046
  34. package/vscode-extension/package.json +0 -514
  35. package/vscode-extension/publish.sh +0 -49
  36. package/vscode-extension/src/api/client.ts +0 -217
  37. package/vscode-extension/src/auth/auth.ts +0 -32
  38. package/vscode-extension/src/commands/auth.ts +0 -44
  39. package/vscode-extension/src/commands/connection.ts +0 -113
  40. package/vscode-extension/src/commands/docs.ts +0 -40
  41. package/vscode-extension/src/commands/pipeline.ts +0 -103
  42. package/vscode-extension/src/commands/server.ts +0 -50
  43. package/vscode-extension/src/commands/smith.ts +0 -112
  44. package/vscode-extension/src/commands/task.ts +0 -43
  45. package/vscode-extension/src/commands/terminal.ts +0 -279
  46. package/vscode-extension/src/commands/workspace.ts +0 -138
  47. package/vscode-extension/src/connection/manager.ts +0 -80
  48. package/vscode-extension/src/docs/fs-provider.ts +0 -94
  49. package/vscode-extension/src/docs/result-provider.ts +0 -33
  50. package/vscode-extension/src/docs/transport.ts +0 -22
  51. package/vscode-extension/src/extension.ts +0 -314
  52. package/vscode-extension/src/statusbar.ts +0 -70
  53. package/vscode-extension/src/terminal/pseudoterm.ts +0 -123
  54. package/vscode-extension/src/views/docs.ts +0 -145
  55. package/vscode-extension/src/views/pipelines.ts +0 -222
  56. package/vscode-extension/src/views/terminals.ts +0 -91
  57. package/vscode-extension/src/views/workspaces.ts +0 -243
  58. package/vscode-extension/tsconfig.json +0 -16
@@ -1,166 +0,0 @@
1
- package com.aion0.forge.ui.toolwindow
2
-
3
- import com.aion0.forge.api.ForgeClient
4
- import com.intellij.icons.AllIcons
5
- import com.intellij.openapi.actionSystem.AnAction
6
- import com.intellij.openapi.actionSystem.AnActionEvent
7
- import com.intellij.openapi.project.Project
8
- import com.intellij.openapi.ui.Messages
9
- import org.jetbrains.plugins.terminal.ShellTerminalWidget
10
- import org.jetbrains.plugins.terminal.TerminalView
11
- import javax.swing.tree.DefaultMutableTreeNode
12
-
13
- class WorkspacesView(project: Project) : ForgeTreeView(project) {
14
-
15
- /** Cache of open smith terminals keyed by tmux session name. Re-clicking a smith
16
- * focuses the existing terminal tab instead of spawning a duplicate. */
17
- private val openedTerminals = mutableMapOf<String, ShellTerminalWidget>()
18
-
19
- override fun rootLabel() = "workspaces"
20
-
21
- override fun reload(): List<DefaultMutableTreeNode> {
22
- val r = ForgeClient.get().request("/api/workspace")
23
- if (r.status == 401 || r.status == 403) return listOf(DefaultMutableTreeNode(TreeNodeData.Hint("πŸ”‘ Tools β†’ Forge: Login")))
24
- if (!r.ok || r.data == null || !r.data.isJsonArray) {
25
- return listOf(DefaultMutableTreeNode(TreeNodeData.Hint("⚠ ${r.error ?: "Not connected"}")))
26
- }
27
- val arr = r.data.asJsonArray
28
- if (arr.size() == 0) return listOf(DefaultMutableTreeNode(TreeNodeData.Hint("No workspaces yet")))
29
- val sorted = arr.toList().sortedBy { it.asJsonObject.get("projectName")?.asString ?: "" }
30
- return sorted.mapNotNull { el ->
31
- val ws = el.asJsonObject
32
- val id = ws.get("id")?.asString ?: return@mapNotNull null
33
- val name = ws.get("projectName")?.asString ?: id
34
- val ar = ForgeClient.get().request("/api/workspace/$id/agents")
35
- val agents = ar.data?.asJsonObject?.getAsJsonArray("agents")
36
- val states = ar.data?.asJsonObject?.getAsJsonObject("states")
37
- val daemon = ar.data?.asJsonObject?.get("daemonActive")?.asBoolean ?: false
38
- val mark = if (daemon) "🟒" else "β—‹"
39
- val node = DefaultMutableTreeNode(TreeNodeData.Workspace("$mark $name (${agents?.size() ?: 0} smiths)", id, name, daemon))
40
- agents?.forEach { aEl ->
41
- val a = aEl.asJsonObject
42
- val aId = a.get("id")?.asString ?: return@forEach
43
- val label = a.get("label")?.asString ?: aId
44
- val icon = a.get("icon")?.asString ?: "πŸ€–"
45
- val s = states?.getAsJsonObject(aId)
46
- val task = s?.get("taskStatus")?.asString ?: "idle"
47
- val smith = s?.get("smithStatus")?.asString ?: "down"
48
- val paused = s?.get("paused")?.asBoolean == true
49
- val tmux = s?.get("tmuxSession")?.asString
50
- val statusEmoji = when {
51
- paused -> "⏸"
52
- smith == "down" -> "β—‹"
53
- smith == "starting"-> "◐"
54
- task == "running" -> "β–Ά"
55
- task == "failed" -> "βœ•"
56
- task == "done" -> "βœ“"
57
- else -> "Β·"
58
- }
59
- node.add(DefaultMutableTreeNode(
60
- TreeNodeData.Smith("$statusEmoji $icon $label ($task)", id, aId, label, task, paused, tmux),
61
- ))
62
- }
63
- node
64
- }
65
- }
66
-
67
- override fun onDoubleClick(data: TreeNodeData, node: DefaultMutableTreeNode) {
68
- when (data) {
69
- is TreeNodeData.Smith -> openSmithTerminal(data)
70
- else -> {}
71
- }
72
- }
73
-
74
- override fun contextActions(data: TreeNodeData, node: DefaultMutableTreeNode): List<AnAction> = when (data) {
75
- is TreeNodeData.Workspace -> if (data.daemonActive) {
76
- listOf(
77
- act("Stop Daemon", AllIcons.Actions.Suspend) { confirmAndDoWs(data.workspaceId, "stop_daemon", "Stop the workspace daemon? Running smiths will be terminated.") },
78
- act("Restart Daemon",AllIcons.Actions.Restart) { runApi(project, "Restart daemon", { restartDaemon(data.workspaceId) }) { refresh() } },
79
- )
80
- } else {
81
- listOf(
82
- act("Start Daemon", AllIcons.Actions.Execute) { runApi(project, "Start daemon", { wsAction(data.workspaceId, "start_daemon") }) { refresh() } },
83
- )
84
- }
85
- is TreeNodeData.Smith -> buildList {
86
- add(act("Open Terminal", AllIcons.Debugger.Console) { openSmithTerminal(data) })
87
- add(act("Send Message", AllIcons.General.Balloon) { promptSendMessage(data) })
88
- if (data.paused) {
89
- add(act("Resume", AllIcons.Actions.Execute) { runApi(project, "Resume ${data.agentLabel}", { wsAction(data.workspaceId, "resume", mapOf("agentId" to data.agentId)) }) { refresh() } })
90
- } else {
91
- add(act("Pause", AllIcons.Actions.Suspend) { runApi(project, "Pause ${data.agentLabel}", { wsAction(data.workspaceId, "pause", mapOf("agentId" to data.agentId)) }) { refresh() } })
92
- }
93
- if (data.taskStatus == "running") {
94
- add(act("Mark Done", null) { runApi(project, "Mark done", { wsAction(data.workspaceId, "mark_done", mapOf("agentId" to data.agentId, "notify" to true)) }) { refresh() } })
95
- add(act("Mark Failed", null) { runApi(project, "Mark failed", { wsAction(data.workspaceId, "mark_failed", mapOf("agentId" to data.agentId, "notify" to true)) }) { refresh() } })
96
- add(act("Mark Idle", null) { runApi(project, "Mark idle", { wsAction(data.workspaceId, "mark_done", mapOf("agentId" to data.agentId, "notify" to false)) }) { refresh() } })
97
- }
98
- if (data.taskStatus == "failed") {
99
- add(act("Retry", AllIcons.Actions.Refresh) { runApi(project, "Retry ${data.agentLabel}", { wsAction(data.workspaceId, "retry", mapOf("agentId" to data.agentId)) }) { refresh() } })
100
- }
101
- }
102
- else -> emptyList()
103
- }
104
-
105
- private fun confirmAndDoWs(wsId: String, action: String, prompt: String) {
106
- val r = Messages.showYesNoDialog(project, prompt, "Forge", Messages.getQuestionIcon())
107
- if (r == Messages.YES) runApi(project, action, { wsAction(wsId, action) }) { refresh() }
108
- }
109
-
110
- private fun restartDaemon(wsId: String): com.aion0.forge.api.ApiResult {
111
- val stop = wsAction(wsId, "stop_daemon")
112
- if (!stop.ok) return stop
113
- Thread.sleep(800)
114
- return wsAction(wsId, "start_daemon")
115
- }
116
-
117
- /** Open an IDE terminal and run `tmux attach -t <session>` β€” works for
118
- * local forge. Remote forge would need a WebSocket-bridged JediTerm
119
- * session (TODO). Reuses an existing terminal tab if one was already
120
- * opened for this smith. */
121
- private fun openSmithTerminal(smith: TreeNodeData.Smith) {
122
- val res = ForgeClient.get().request(
123
- "/api/workspace/${smith.workspaceId}/agents",
124
- method = "POST",
125
- body = mapOf("action" to "open_terminal", "agentId" to smith.agentId),
126
- )
127
- val tmux = res.data?.asJsonObject?.get("tmuxSession")?.asString ?: smith.tmuxSession
128
- if (tmux.isNullOrBlank()) {
129
- notify(project, "Forge: smith ${smith.agentLabel} has no tmux session yet β€” start the daemon first.", com.intellij.notification.NotificationType.WARNING)
130
- return
131
- }
132
- val existing = openedTerminals[tmux]
133
- if (existing != null && !com.intellij.openapi.util.Disposer.isDisposed(existing)) {
134
- // Surface the existing tab in the Terminal tool window.
135
- val tw = com.intellij.openapi.wm.ToolWindowManager.getInstance(project).getToolWindow("Terminal")
136
- tw?.activate(null)
137
- existing.requestFocusInWindow()
138
- return
139
- }
140
- val terminalView = TerminalView.getInstance(project)
141
- val widget = terminalView.createLocalShellWidget(project.basePath ?: System.getProperty("user.home"), "forge: ${smith.agentLabel}")
142
- openedTerminals[tmux] = widget
143
- com.intellij.openapi.util.Disposer.register(widget) { openedTerminals.remove(tmux) }
144
- // Force UTF-8 + 256-color terminfo so the tmux UI doesn't render as garbled
145
- // box-drawing characters in JediTerm. `-u` opts into UTF-8, `-2` forces 256-color.
146
- widget.executeCommand("TERM=xterm-256color tmux -2 -u attach -t \"$tmux\" || TERM=xterm-256color tmux -2 -u new -A -s \"$tmux\"")
147
- }
148
-
149
- private fun promptSendMessage(smith: TreeNodeData.Smith) {
150
- val text = Messages.showMultilineInputDialog(
151
- project,
152
- "Send message to ${smith.agentLabel}",
153
- "Forge: Send Message",
154
- "",
155
- null, null,
156
- ) ?: return
157
- if (text.isBlank()) return
158
- runApi(project, "Send message to ${smith.agentLabel}",
159
- { wsAction(smith.workspaceId, "message", mapOf("agentId" to smith.agentId, "content" to text)) },
160
- ) { refresh() }
161
- }
162
-
163
- private fun act(name: String, icon: javax.swing.Icon?, run: () -> Unit) = object : AnAction(name, null, icon) {
164
- override fun actionPerformed(e: AnActionEvent) = run()
165
- }
166
- }
@@ -1,88 +0,0 @@
1
- <idea-plugin>
2
- <id>com.aion0.forge</id>
3
- <name>Forge Vibe Coding</name>
4
- <version>0.1.0</version>
5
- <vendor email="liuzhen1984@gmail.com" url="https://github.com/aiwatching/forge">aion0</vendor>
6
-
7
- <description><![CDATA[
8
- <p>Drive your <a href="https://github.com/aiwatching/forge">Forge</a> instance from
9
- the IDE β€” workspaces, agents, terminals, pipelines and docs in one tool window.</p>
10
-
11
- <p><b>⚠ Requires Forge running locally.</b> Install once:</p>
12
- <pre>npm install -g @aion0/forge
13
- forge server start</pre>
14
- <p>Default port <code>8403</code>. Configure remote forges under
15
- <b>Settings β†’ Tools β†’ Forge</b>.</p>
16
-
17
- <h3>Features</h3>
18
- <ul>
19
- <li>Workspaces β€” daemon control, multi-agent smiths, tmux attach, pause/resume/retry</li>
20
- <li>Terminals β€” per-project claude sessions, double-click to resume, right-click β†’ Open With for any agent</li>
21
- <li>Pipelines β€” bindings + run details with per-node prompt / result / diff viewer</li>
22
- <li>Docs β€” open files in editor, "open terminal here"</li>
23
- <li>Multi-connection β€” local + remote forges with status-bar switcher</li>
24
- </ul>
25
- ]]></description>
26
-
27
- <change-notes><![CDATA[
28
- <h3>0.1.0</h3>
29
- <ul>
30
- <li>Initial scaffold: tool window shell, settings page, login flow, multi-connection support.</li>
31
- </ul>
32
- ]]></change-notes>
33
-
34
- <depends>com.intellij.modules.platform</depends>
35
- <depends>org.jetbrains.plugins.terminal</depends>
36
-
37
- <extensions defaultExtensionNs="com.intellij">
38
- <!-- Persisted application-level state (connections + active connection). -->
39
- <applicationService serviceImplementation="com.aion0.forge.connection.ConnectionManager"/>
40
- <applicationService serviceImplementation="com.aion0.forge.api.ForgeClient"/>
41
- <applicationService serviceImplementation="com.aion0.forge.auth.Auth"/>
42
-
43
- <!-- Tool window: lives on the right side, contains tabs for each section. -->
44
- <toolWindow
45
- id="Forge"
46
- anchor="left"
47
- secondary="true"
48
- icon="/icons/forge.svg"
49
- factoryClass="com.aion0.forge.ui.toolwindow.ForgeToolWindowFactory"/>
50
-
51
- <!-- Settings page (Preferences β†’ Tools β†’ Forge). -->
52
- <applicationConfigurable
53
- parentId="tools"
54
- instance="com.aion0.forge.settings.ForgeConfigurable"
55
- id="com.aion0.forge.settings.ForgeConfigurable"
56
- displayName="Forge"/>
57
-
58
- <!-- Status bar widget β€” connection state + click-to-switch. -->
59
- <statusBarWidgetFactory
60
- id="com.aion0.forge.statusbar"
61
- implementation="com.aion0.forge.ui.toolwindow.ForgeStatusBarWidgetFactory"
62
- order="last"/>
63
-
64
- <notificationGroup id="Forge" displayType="BALLOON"/>
65
- </extensions>
66
-
67
- <actions>
68
- <group id="com.aion0.forge.actions" text="Forge" popup="true">
69
- <action id="com.aion0.forge.action.LoginAction"
70
- class="com.aion0.forge.action.LoginAction"
71
- text="Forge: Login"
72
- description="Authenticate against the active Forge server."/>
73
- <action id="com.aion0.forge.action.LogoutAction"
74
- class="com.aion0.forge.action.LogoutAction"
75
- text="Forge: Logout"
76
- description="Clear the saved token for the active connection."/>
77
- <action id="com.aion0.forge.action.SwitchConnectionAction"
78
- class="com.aion0.forge.action.SwitchConnectionAction"
79
- text="Forge: Switch Connection…"
80
- description="Pick a different Forge server."/>
81
- <action id="com.aion0.forge.action.OpenWebUIAction"
82
- class="com.aion0.forge.action.OpenWebUIAction"
83
- text="Forge: Open Web UI"
84
- description="Open the Forge web UI in the default browser."/>
85
- <add-to-group group-id="ToolsMenu" anchor="last"/>
86
- </group>
87
- </actions>
88
- </idea-plugin>
@@ -1,3 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="currentColor">
2
- <path d="M12 2L3 7v6c0 5 3.5 9.5 9 11 5.5-1.5 9-6 9-11V7l-9-5zm0 4.5l5 2.8v3.4l-5-2.8-5 2.8V9.3l5-2.8zm-5 6.4l5 2.8v5.6c-3.4-1.4-5-4.6-5-7.6v-.8zm10 .8c0 3-1.6 6.2-5 7.6v-5.6l5-2.8v.8z"/>
3
- </svg>
@@ -1,11 +0,0 @@
1
- .vscode/**
2
- .vscode-test/**
3
- src/**
4
- .gitignore
5
- .yarnrc
6
- vsc-extension-quickstart.md
7
- tsconfig.json
8
- **/.eslintrc.json
9
- **/*.map
10
- **/*.ts
11
- package-lock.json
@@ -1,48 +0,0 @@
1
- # Forge VSCode Extension
2
-
3
- Native VSCode integration for [Forge](https://github.com/aiwatching/forge).
4
-
5
- ## What it does
6
-
7
- - **Sidebar** β€” workspaces, smiths, active terminals, and background tasks at a glance
8
- - **Native terminals** β€” attach to or create Forge tmux sessions in VSCode's terminal panel (uses VSCode's own Pseudoterminal API; sessions show up next to your regular terminals)
9
- - **Send selection** β€” pipe selected code to a running Forge terminal
10
- - **Notifications** β€” smith bell events surface as VSCode notifications
11
- - **Status bar** β€” connection indicator + quick command access
12
-
13
- ## Setup
14
-
15
- 1. Install Forge CLI: `npm install -g @aion0/forge`
16
- 2. Start the server: `forge server start`
17
- 3. Install this extension (VSCode β†’ "Install from VSIX..." or marketplace)
18
- 4. Cmd/Ctrl+Shift+P β†’ `Forge: Login` β†’ enter your admin password
19
-
20
- The token is stored in VSCode's SecretStorage and reused across sessions.
21
-
22
- ## Settings
23
-
24
- | Key | Default | Description |
25
- |-----|---------|-------------|
26
- | `forge.serverUrl` | `http://localhost:8403` | Forge HTTP server |
27
- | `forge.terminalUrl` | `ws://localhost:8404` | Terminal WebSocket |
28
- | `forge.autoStart` | `false` | Spawn `forge server start` on activation if unreachable |
29
- | `forge.notifications.enabled` | `true` | Smith-bell β†’ VSCode notification |
30
- | `forge.refreshInterval` | `5` | Tree refresh interval (seconds) |
31
-
32
- ## Local install
33
-
34
- ```bash
35
- cd vscode-extension
36
- npm install
37
- npm run package # produces forge-vscode.vsix
38
- code --install-extension forge-vscode.vsix
39
- ```
40
-
41
- ## Develop
42
-
43
- ```bash
44
- cd vscode-extension
45
- npm install
46
- npm run watch # in one terminal
47
- # In VSCode: F5 to launch Extension Development Host
48
- ```
Binary file
@@ -1,3 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
2
- <path d="M12 2L3 7v6c0 5 3.5 9.5 9 11 5.5-1.5 9-6 9-11V7l-9-5zm0 4.5l5 2.8v3.4l-5-2.8-5 2.8V9.3l5-2.8zm-5 6.4l5 2.8v5.6c-3.4-1.4-5-4.6-5-7.6v-.8zm10 .8c0 3-1.6 6.2-5 7.6v-5.6l5-2.8v.8z"/>
3
- </svg>