Skip to content
Developer Tools

VS Code Extension

The AMI / 3forge Language Support extension (3forge.vscode-ami) brings AmiScript and AMISQL language intelligence and live debugging into VS Code. This page covers installing the extension, connecting it to AmiCore, editing a live Web session, and diagnosing the connection failures that account for most first-run problems.

The extension is a thin client. The language and debug servers run inside AmiCore (see Language and Debug Servers), and the extension connects to them over AmiCore's RPC WebSocket port. It never starts AmiCore itself.

What to expect on a first run

3 things account for most first-run confusion:

  • Almost everything is bound to a live Web session. That session is created by logging in to AmiCore's Web UI in a browser, then handing its id to the extension. Until then, the extension gives generic language support and empty views.
  • Applying a change neither re-runs the object nor writes it to disk. Re-executing and persisting are separate actions. See Editing a Live Session.
  • The connection settings depend on how AmiCore is configured, not on the extension. The REST port and its scheme in particular vary between a stock local build and a shared deployment.

Features

  • Language support for .ami (AmiScript) and .amisql files: completion, hover, signature help, diagnostics, and formatting, backed by AmiCore's own parser.
  • Workspace navigation: go-to-definition, find-references, workspace symbols, and rename across .amisql / .ami / .properties.
  • Live debugging: set breakpoints and step through AmiScript callbacks (Web) and Center targets (timers, triggers, procedures, methods).
  • Deployment views: browse a live deployment's layouts, session editors, Center debug targets, and documentation from the AMI sidebar.
  • Query & run helpers: run and validate AmiScript / AMISQL against the connected instance with a keystroke.

Prerequisites

Requirement Detail
VS Code 1.75 or newer, plus the extension .vsix
A running AmiCore instance Required for all live features. It must serve the RPC WebSocket endpoint on ami.rpc.ws.port (default 33334) with the LSP plugin loaded. The endpoint binds to loopback by default, so the simplest setup is an AmiCore on the same machine as VS Code. See Language and Debug Servers for additional configuration details
Credentials An AmiCore username and password
A browser To log in and create the Web session the extension binds to
Java 17 Only for Offline Mode. Not needed when connecting to a running AmiCore

Older builds cannot serve ws mode

The language server ships as a server-side plugin. A build that predates it has no ami.rpc.ws.port in its configuration and no WebSocket to connect to, so the extension cannot bind. If that property is absent from the instance's configuration, or nothing is listening on the port, the build is too old whatever version of the extension is installed.

Install

Download the vscode-ami-0.2.35.vsix file from the "Files" section of the 3forge Client Portal, then install it one of 2 ways.

  1. Open the Extensions view (Ctrl+Shift+X).
  2. Click the … menu at the top of the view, then select Install from VSIX…
  3. Select the .vsix file.
  4. When prompted, Reload the window.
code --install-extension vscode-ami-0.2.35.vsix --force

--force overwrites any previously installed version. Use it when upgrading, otherwise the debug adapter can stay on the previous version.

Windows

The bare code on your PATH may resolve to the GUI launcher, which does not accept --install-extension. Use the CLI launcher under the install's bin directory instead e.g: "%LOCALAPPDATA%\Programs\Microsoft VS Code\bin\code.cmd" --install-extension <vsix> --force

To confirm what is installed:

code --list-extensions --show-versions
# -> 3forge.vscode-ami@0.2.35

Open the Command Palette (Ctrl+Shift+P) and type AMI. The extension's commands appear, and a .ami or .amisql file now opens with AmiScript syntax highlighting. Commands do not appear until the window is reloaded. To upgrade later, install a newer .vsix the same way (with --force on the CLI) and reload the window.

Connect

Connecting means pointing the extension at 3 endpoints on the AmiCore host, storing credentials, and binding to a live Web session.

Connection Channels

The extension talks to 3 logical endpoints, all on the host given by ami.lsp.host:

Channel Endpoint Used for
Web UI the Web port, 33333 HTTPS or 33332 HTTP Logging in. This is where the session id comes from
REST /3forge_rest/* on ami.rest.port Running queries, listing sessions, applying editor changes
WebSocket /lsp and /dap on ami.websocket.port Diagnostics, completion, hover, and step debugging

Keeping these 3 separate is what makes the common failures legible: a working login proves nothing about REST, and a working REST channel proves nothing about the language server.

Find Your Instance's Values

The client settings below are derived from properties on the AmiCore side. Read them from the instance's own configuration: an override in config/local.properties wins, otherwise the shipped defaults.properties applies.

Read this on AmiCore Sets this in VS Code
The host AmiCore runs on ami.lsp.host
ami.rpc.ws.port, default 33334 ami.websocket.port
ami.rest.uses.web.port Decides where REST is served, and so the 2 rows below
...set to a Web component name: that component's own http.port / https.port. A stock install serves HTTPS on 33333 ami.rest.port
...set to false: REST's own socket, ami.rest.http.port or ami.rest.https.port ami.rest.port
The scheme actually served by whichever port the 2 rows above resolved to ami.rest.scheme
ami.db.debug.enabled Not a client setting. It must be true before the Center Debug Targets view has anything in it

A stock local install needs none of this looked up, because the defaults in the next section already match it. Look these up when connecting to a deployment someone else configured, or when the defaults do not work.

Filling in the host and port from a deployment on disk

Where the workspace contains the deployment's own files, the extension can read the connection details rather than having them typed. In Workspace mode, select the instance in the Deployments view and run AMI: Connect. It sets ami.lsp.host and ami.rest.port from that deployment's local.properties, then prompts for the session id.

2 things it does not do, so check both afterwards:

  • It does not set ami.rest.scheme, which stays https. The port it picks is the first of ami.port, https.port, or http.port found, so an HTTP-only deployment yields a plain-HTTP port against an HTTPS scheme. That combination fails with EPROTO or "wrong version number".
  • It writes at workspace scope, not user scope, so the values land in the folder's .vscode/settings.json and override anything set in User Settings.

Set the Connection Settings

Open Preferences: Open User Settings (JSON) and add the connection settings. These values suit an AmiCore running locally on stock ports:

1
2
3
4
5
6
"ami.lsp.mode": "ws",
"ami.lsp.host": "localhost",
"ami.websocket.port": 33334,
"ami.rest.port": 33333,
"ami.rest.scheme": "https",
"ami.auth.username": "demo"
Setting What it is
ami.lsp.mode Language server transport: auto, ws, or stdio. ws connects to a running AmiCore; stdio runs a local offline linter instead
ami.lsp.host Host of the AmiCore instance. Used for the WebSocket endpoints and the REST channel
ami.websocket.port The extension's name for AmiCore's RPC WebSocket port. Match it to the server's ami.rpc.ws.port, default 33334
ami.rest.port Port serving /3forge_rest/*. Default 33333
ami.rest.scheme http or https for that port. The port number does not imply the scheme
ami.auth.username AmiCore username for REST authentication. Default demo

Match ami.websocket.port to the server's ami.rpc.ws.port

The 2 properties are named differently on each side, and AmiCore has a separate property that happens to share the client's name. The extension's ami.websocket.port must equal AmiCore's ami.rpc.ws.port, which is the endpoint serving /lsp and /dap and defaults to 33334.

AmiCore's own ami.websocket.port is an unrelated, opt-in WebSocket streaming listener for browsers, commented out by default and shipped with ami.websocket.auth.plugin.class=DISABLED. Do not enable it to satisfy the extension.

REST is not always on the Web port

ami.rest.port defaults to 33333, the Web HTTPS port. That is correct only when AmiCore sets ami.rest.uses.web.port to a Web component name, which is the stock default. With ami.rest.uses.web.port=false, common in development so local clients can skip the self-signed certificate, REST binds its own socket in plain HTTP. Point ami.rest.port at ami.rest.http.port and set ami.rest.scheme=http.

Do not copy REST values between deployments. A port that is right for a shared server is usually wrong locally, and the symptom is "Rest not enabled on this port".

Prefer 127.0.0.1 to localhost for a local instance

AmiCore binds the RPC WebSocket to IPv4 loopback by default, through ami.rpc.ws.bindAddress=loopback. On a dual-stack machine, localhost can resolve to ::1 first and the connection is refused, which surfaces as a Node AggregateError and an offline language server. Setting ami.lsp.host to 127.0.0.1 avoids it.

Self-signed certificates need no handling in the extension, because ami.tls.rejectUnauthorized defaults to false. A browser still warns at login, and that warning is safe to proceed past on a development instance.

Bind to a Session

  1. Run AMI: Set Credentials. The password is stored in the OS keychain, not in settings.json. The username comes from ami.auth.username.
  2. Run AMI: Switch to Live.
  3. Log in to AmiCore's Web UI to create a session. For a local instance on the Web's HTTPS port that is https://localhost:33333/3forge, accepting the self-signed certificate.
  4. Run AMI: Set Session ID and supply the session's id. Read it from Dashboard -> Admin Tool -> Sessions, or from showSessions().__SESSIONID.
  5. (Optional) Set ami.centerId. Only needed for Center-target debugging where several Centers run in one instance.

The connection is good when the status bar reads AMI LSP · WebSocket .../lsp · session-bound and AMI: Center + Web session, and the AMI activity-bar container fills with Layouts, datamodels, and Center Debug Targets. The status bar reads offline lint rather than session-bound whenever the transport is not ws or no session id is set.

AMI: Show Connection Status reports what the extension currently reaches, and why not where it does not. AMI: Print Language Server Status to Log writes the same detail to the AMI output channel.

Changed connection settings need a window reload

AMI: Restart Language Server does not reliably re-read a changed ami.lsp.host, or other ami.* connection settings. The WebSocket client can keep the stale value and stay disconnected. Run Developer: Reload Window after changing a connection setting, before concluding the new value is wrong.

Offline Mode

To lint .ami and .amisql files with no running AmiCore, set ami.lsp.mode to stdio, point ami.lsp.amiHome at an AmiCore installation and ami.lsp.javaHome at a Java 17 JDK, then run AMI: Setup Sidecar (Offline LSP) Mode…. This spawns a local sidecar JVM that runs AmiCore's own parser, giving completion, diagnostics, formatting, and workspace symbols with no session and no login.

The amilsp plugin is compiled for Java 17 and loaded from the install's plugins directory, so the plugin must be present in the installation given by ami.lsp.amiHome.

Live-only features need a running instance: editor-aware callback validation, debugging, and the live deployment views.

auto falls back only when the sidecar is configured

In auto mode the extension tries the WebSocket first and falls back to the sidecar only if both ami.lsp.amiHome and ami.lsp.javaHome are set. With either unset, which is the default, a failed WebSocket connection is reported as an error rather than silently downgraded, and the notification names the missing settings.

Editing a Live Session

A live session editor is a temporary file bound to an object in the running session. Opening the object binds the buffer: open a callback or datamodel editor from Web Session Editors, or run AMI: Open in VS Code.

Saving that buffer reaches AmiCore. Because ami.applyOnSave defaults to true, Ctrl+S sends the code and applies it in one step, and the status bar reports Saved + applied. 2 things saving does not do:

  • It does not re-execute the object.
  • It does not write anything to disk.

The actions available on a bound buffer are:

Action What it does
AMI: Validate (Ctrl+Enter) Checks the buffer without sending it. Not a prerequisite for applying
AMI: Apply to AMI Sends the buffer and commits it to the session, after a confirmation prompt
AMI: Apply & Run (Alt+Enter) Applies, then re-executes the object. For a datamodel this runs it immediately
AMI: Save to Layout (persist to disk) Writes the session's layout out to disk
AMI: Pull from Live (Discard Local Edits) Re-fetches the live code over local edits

Set ami.applyOnSave to false to separate the 2 halves of a save. Saving then stages the code on the server without committing it, reporting Saved (not yet applied), and applying becomes an explicit action. This is worth doing where an applied callback runs on every save.

An applied change is not a persisted change

Applying commits to the running session only. Without Save to Layout, the change is lost when the session ends.

Applying a datamodel does not re-run it

Apply commits the definition. The previous result set stays on screen until something re-executes the datamodel, so a reader who checks the data rather than the definition will conclude the apply failed. Use Apply & Run to apply and re-execute in one step.

Opening a layout switches the session id

Opening a layout from the Layouts view starts a headless session and repoints ami.sessionId at it. Anything applied afterwards goes to that headless session rather than to the browser session being watched, and the apply reports success either way.

Browse layouts first, then run AMI: Set Session ID to point back at the intended session. Where an applied change does not appear, check the target with AMI: Show Connection Status before changing the code.

No .ami file on disk is normal in Live mode

Live editors are session-bound and held in memory. A .ami file appears on disk only after Save to Layout.

A Worked Example: Change a Datamodel and See It Update

This is the shortest path that avoids both traps above, the wrong session and the missing re-run. The order matters: bind the session last, after any browsing in the Layouts view.

  1. Log in to the Web UI in a browser and open the application containing the datamodel.
  2. Read the session id from Dashboard -> Admin Tool -> Sessions.
  3. Browse the Layouts view now, if at all. Opening a layout there repoints ami.sessionId at a headless session, so anything done in that view belongs before the session is bound.
  4. Run AMI: Set Session ID and supply the id from step 2. Doing this after step 3 is what makes the rest of the sequence land in the right place.
  5. Open the datamodel's editor from Web Session Editors, not from Layouts. Web Session Editors binds to the session set in step 4, while Layouts opens a layout in a headless session of its own.
  6. Edit the definition, then press Ctrl+S. The status bar reports Saved + applied.
  7. The definition is now live, but the panel still shows the previous result set. Run AMI: Apply & Run (Alt+Enter) to re-execute the datamodel, and the panel updates.
  8. Run AMI: Save to Layout (persist to disk) to keep the change beyond the session's life.

If the panel does not update after step 7, confirm the target before editing anything further:

  • Run AMI: Show Connection Status and check the session id is still the one from step 2. If it is not, a layout was opened in between; re-run AMI: Set Session ID, then Apply & Run again.
  • Run AMI: Show DM Output to read the datamodel's current output directly, which separates an apply that did not land from a query returning what it always returned.
  • Run AMI: Close Headless Session to discard a headless session created by browsing layouts.

What Needs a Session, and What Does Not

ami.sessionId is required for diagnostics, completion, and hover, and for the live panel, datamodel, and layout editors. Saving a bound buffer also does nothing at all, silently, while the session id is unset.

Center SQL queries and the Center Debug Targets, meaning timers, triggers, procedures, and methods, work as soon as AmiCore is reachable and credentials are set, with no Web session at all.

Language and Navigation

Language Editing

Open any .ami or .amisql file. As you type:

  • Completion on . and :, covering member methods, global functions, keywords, and DDL OFTYPE / USE slots. Local variables complete too, typed to their declared class.
  • Hover documentation and signature help, on ( and ,.
  • Diagnostics on open, change, and save, produced by AmiCore's real compiler plus AMISQL idiom checks.
  • Formatting: Format Document applies AmiCore's canonical formatter.

In ws mode with a session bound, callbacks are validated with their full context, meaning their layout, this, and linked variables, so diagnostics match how the callback actually runs.

Workspace Navigation

With a workspace folder open:

  • Go to Definition (F12), including the nearest-prior declaration for shadowed locals.
  • Find All References (Shift+F12).
  • Rename Symbol (F2), which propagates across .amisql, .ami, and .properties files. A local variable renames per binding: a shadowed declaration in an inner block is left alone, and a member access that happens to share the name (row.total next to a local total) is never rewritten.
  • Workspace symbol search (Ctrl+T) for tables, columns, named SQL objects, methods, panels, datamodels, and properties.

Note

Save files before renaming. Unsaved buffers are not yet reindexed, so rename ranges resolve against the last-saved content.

The AMI Sidebar

The extension contributes an AMI activity-bar container with 2 faces. Switch between them with AMI: Switch to Live and AMI: Switch to Workspace.

Working against a running instance:

View Shows
Layouts Layouts available in the live deployment. Opening one starts a headless session
Web Session Editors Open callback and datamodel editors in the live Web session
Center Debug Targets Timers, triggers, procedures, and methods available to debug, each with an inline ▷ Fire action. Requires ami.db.debug.enabled=true on the Center

Working with files on disk:

View Shows
Deployments AmiCore deployments discovered in the workspace, meaning folders with a local.properties, with type, port, and connection status
Layout File The current layout file's structure
Workspace Symbols Tables, columns, named SQL objects, methods, panels, datamodels, and properties
References Results of Find References Here

Documentation, the 3forge Enterprise reference, is present in both.

Debugging

The extension registers an amiscript debug type that attaches VS Code's debugger to AmiCore's in-JVM debug adapter over the WebSocket port. It provides gutter breakpoints, step over, in, and out (F10, F11, Shift+F11), the Call Stack and Variables panels, Watch, hover, and inline values.

There are 2 kinds of target:

  • Web callbacks: a datamodel onProcess, a panel callback, and similar. The callback editor must be open in the session for the target to resolve.
  • Center targets: a timer, trigger, procedure, or method, debugged through the Center freeze debugger. Requires ami.db.debug.enabled=true on the Center, which is off by default and needs a restart.

Quickest Paths

  • Active editor: open the callback to debug and run AMI: Debug. The extension derives the target from the file.
  • Center target: in the Center Debug Targets view, use Attach Debugger to Center Target, set a breakpoint, then use the inline ▷ Fire action to trigger it.

Using launch.json

1
2
3
4
5
6
7
8
{
  "type": "amiscript",
  "request": "attach",
  "name": "AMI: Attach to callback",
  "host": "localhost",
  "port": 33334,
  "handle": "callback:DATAMODEL:debug/onProcess"
}
1
2
3
4
5
6
7
8
{
  "type": "amiscript",
  "request": "attach",
  "name": "AMI: Attach to timer",
  "host": "localhost",
  "port": 33334,
  "target": "center:timer:myTimer:script"
}

host and port default to ami.lsp.host and ami.websocket.port, and sessionId to ami.sessionId, so most fields can be omitted. handle and target are mutually exclusive. Set breakpoints in the gutter, press F5, and step. For the full target-reference grammar and protocol, see Language and Debug Servers.

A Center attach checks that the named target exists before the session starts, so a typo fails immediately with a message naming the kind and id rather than leaving a breakpoint that can never fire. Target names are case-sensitive.

One controller at a time

A Center attach takes an exclusive claim on the Center debugger, so a second attach is refused with a message naming the holder. The claim is released when the session detaches. Where a client died without releasing it, clear it with center_debug("detach"). The claim does not lock out the center_debug command surface, so an operator can still step or resume a freeze. See Center Debugger.

Methods are signature-only in the code view

The Center exposes no live method body, so Show Debug Target Code on a method shows its signature plus guidance rather than the source. To set a breakpoint, arm the line directly, where line 1 is the CREATE METHOD signature and line 2 the first body statement, or open the body from the schema file. Timers, triggers, and procedures open in full.

Reference

Command Reference

Almost every command sits under the AMI category, so typing AMI in the Command Palette lists it with its title. The commands below are those belonging to a workflow that cannot be guessed from a title. The rest are refresh, reveal, and filter actions, mostly surfaced as context actions on the sidebar views, and are best found in the palette.

A few actions are not in the palette at all

6 commands are deliberately hidden from the Command Palette and can only be reached from a view, a context menu, or by clicking a tree item. The one that matters is Open Layout (Headless Session), which has no palette entry and no menu entry: it runs when a layout is clicked in the Layouts view. That is why opening a layout repoints the session id without an obvious command having been run. See Editing a Live Session.

Connection and mode

Command Purpose
AMI: Set Credentials Store the AmiCore login. The password goes to the OS keychain
AMI: Set Session ID Set the live Web session id
AMI: Switch to Live / Switch to Workspace Toggle the sidebar between the live and workspace view sets
AMI: Show Connection Status What the extension currently reaches, and why not where it does not
AMI: Connect On a Deployments entry in Workspace mode: set ami.lsp.host and ami.rest.port from the discovered deployment, then prompt for the session id

Language server

Command Purpose
AMI: Restart Language Server Reconnect or restart the language server
AMI: Print Language Server Status to Log Connection status, written to the AMI output channel
AMI: Setup Sidecar (Offline LSP) Mode… Configure the offline stdio transport
AMI: Rebuild Workspace Symbol Index Re-index the workspace
AMI: Show Workspace Index Status Inspect the symbol index's state
AMI: Show Activation Log What the extension did on startup, for diagnosing a failure to activate

Editing live code

Command Purpose
AMI: Open in VS Code Open a live session editor as a local file
AMI: Validate Check the buffer without sending it
AMI: Apply to AMI Commit the buffer to the running session
AMI: Apply & Run Apply, then re-execute
AMI: Pull from Live (Discard Local Edits) Re-fetch the live code over local edits
AMI: Save to Layout (persist to disk) Persist the session's layout to disk
AMI: Show DM Output Read a datamodel's current output, to tell an apply that did not land from a query returning what it always did
AMI: Close Headless Session Discard a headless session, including one created by opening a layout

Queries

Command Purpose
AMI: New Query Editor Open a scratch query editor
AMI: Run Query (current selection or document) Run the selection, or the whole document

Debugging

Command Purpose
AMI: Debug Attach the debugger to the active editor's callback
AMI: Attach Debugger to Center Target Start a Center debug session
AMI: Show Debug Target Code Open a Center target's source
AMI: Fire Center Target Trigger a timer, procedure, or method to drive a breakpoint
AMI: New… (create from template) / Edit Definition (drop & recreate) Create a Center target, or redefine an existing one

Settings Reference

Connection

Setting Default Purpose
ami.lsp.host localhost Host of the AmiCore instance, used for the WebSocket endpoints and the REST channel
ami.websocket.port 33334 AmiCore's RPC WebSocket port, hosting both /lsp and /dap. The AmiCore-side property is ami.rpc.ws.port
ami.rest.port 33333 Port serving /3forge_rest/*. 33333 is the Web HTTPS port and is right only where AmiCore has ami.rest.uses.web.port=<Web component>. Otherwise use ami.rest.http.port or ami.rest.https.port
ami.rest.scheme https Scheme for ami.rest.port. The port number does not imply the scheme, and AmiCore's standalone REST socket is commonly plain HTTP
ami.auth.username demo AmiCore login username. The password lives in the OS keychain, set via AMI: Set Credentials
ami.sessionId (none) Live Web session id, the Web session's __SESSIONID
ami.centerId (none) Target Center for Center debugging, in multi-Center deployments
ami.tls.rejectUnauthorized false Whether to verify TLS certificates. Development instances typically use self-signed certificates
ami.tls.caCertPath (none) CA certificate used to verify AmiCore's certificate when rejectUnauthorized is on

Language server

Setting Default Purpose
ami.lsp.mode auto Transport: auto, ws, or stdio
ami.lsp.amiHome (none) Offline mode: the AmiCore install, given as the install root, its lib directory, or a marker jar directly
ami.lsp.javaHome (none) Offline mode: the Java 17 JDK used to spawn the sidecar JVM
ami.lsp.sidecarVmArgs [] Extra JVM arguments for the sidecar, appended after the required Java 17 --add-opens flags
ami.lsp.reconnectDelayMs 3000 Delay before reconnecting after a dropped connection
ami.schema.autoRefreshMs 30000 How often to refresh the live Center schema, feeding the completion cache and Center Debug Targets. 0 disables it

Editing

Setting Default Purpose
ami.applyOnSave true Whether saving a bound editor applies the change as well as sending it

Deployment discovery

These affect Workspace mode only, where the extension scans for folders containing a local.properties:

Setting Default Purpose
ami.deployment.env {} Per-workspace environment snapshot for resolving ${env.VAR} in local.properties. Takes precedence over ami.deployment.envFiles
ami.deployment.envFiles [] Env files, KEY=VALUE per line, consulted during discovery. Earlier files win on conflict
ami.deployment.exclude [] Extra folder names to skip, additive with the built-in defaults

Keybinding Reference

Action Keybinding Applies to
AMI: Apply & Run Alt+Enter .ami files
AMI: Validate Ctrl+Enter .ami and .amisql files
AMI: Run Query Ctrl+Shift+Enter .ami and .amisql files

Troubleshooting

Symptom Likely cause Fix
Commands do not appear after install The window was not reloaded Reload the VS Code window
Nothing happens on save, with no message ami.sessionId is not set, so the save is discarded silently Run AMI: Set Session ID
An applied change does not appear, but the apply reported success ami.sessionId points at a headless session, created by opening a layout from the Layouts view Run AMI: Set Session ID with the intended session id, then apply again
A datamodel's definition applied, but its data did not change Apply commits the definition without re-executing it Run AMI: Apply & Run
An applied change is lost when the session ends The change was never persisted Run AMI: Save to Layout (persist to disk)
Connected, but no diagnostics or completion No session id, or it points at a session that has ended Re-run AMI: Set Session ID
Editor-aware features missing, generic types only Session id not set Run AMI: Set Session ID
"Rest not enabled on this port", queries failing as unparseable, or an empty Layouts view ami.rest.port points at a port AmiCore does not serve REST from Match the server's REST configuration, and set ami.rest.scheme to suit
REST errors mentioning EPROTO or "wrong version number" Speaking HTTPS to a plain-HTTP REST port Set ami.rest.scheme=http
REST fails with 401 No stored password Run AMI: Set Credentials
No completion in ws mode The language server is unreachable Check that ami.websocket.port matches the server's ami.rpc.ws.port, that ami.rpc.ws.plugin.classes includes LSP, and that the port is listening
A changed connection setting appears to have no effect AMI: Restart Language Server does not reliably re-read ami.* connection settings Run Developer: Reload Window
"AMI language server offline", with a Node AggregateError in the output channel ami.lsp.host is localhost, resolving to ::1 on a dual-stack machine, while the endpoint binds IPv4 loopback Set ami.lsp.host to 127.0.0.1, then reload the window
"AMI Language Server offline" in auto mode The WebSocket failed and no sidecar is configured Start AmiCore, or set ami.lsp.amiHome and ami.lsp.javaHome to allow the fallback
The login page never loads, or the connection times out The Web or RPC ports are not reachable. A remote deployment's ports are often firewalled Use a local instance, or have the ports opened
Certificate warnings in the browser Development instances use self-signed certificates Proceed past the warning. The extension itself accepts them by default
"Configured debug type 'amiscript' is not supported" The extension was not reinstalled after an upgrade Reinstall the .vsix with --force, then reload
The Center Debug Targets view is empty The Center debugger is off Set ami.db.debug.enabled=true on the Center and restart it
Debug attach fails to resolve the target Wrong handle or target, or the target is unavailable Verify the target id. For a Web callback, make sure its editor is open in the session
A breakpoint never hits The code did not run, or the line is wrong Trigger the callback, or use Fire Center Target after attaching